From: github-actions Date: Mon, 13 May 2024 17:29:58 +0000 (+0000) Subject: Publish autogenerated nightly docs X-Git-Url: http://internal-gitweb-vhost/script/%22https:/database/scripts/struct.VarInt.html?a=commitdiff_plain;h=8ac8f511f1490106a2b35bd4099ff4dd4d9e06b6;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 deleted file mode 100644 index d53085a87b..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/all.html +++ /dev/null @@ -1,2 +0,0 @@ -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/descriptor/checksum/fn.calc_checksum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum.html deleted file mode 100644 index 7cba4a69ec..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 7050e1d44a..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.calc_checksum_bytes.html +++ /dev/null @@ -1,3 +0,0 @@ -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/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/index.html deleted file mode 100644 index b986473868..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/index.html +++ /dev/null @@ -1,5 +0,0 @@ -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
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/sidebar-items.js deleted file mode 100644 index c3609de7d4..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"fn":[["calc_checksum","Compute the checksum of a descriptor, excludes any existing checksum in the descriptor string from the calculation"],["calc_checksum_bytes","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/enum.Descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html deleted file mode 100644 index 37edf56b06..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html +++ /dev/null @@ -1,190 +0,0 @@ -Descriptor in bdk::descriptor - Rust
pub enum Descriptor<Pk>where
    Pk: MiniscriptKey,
{ - Bare(Bare<Pk>), - Pkh(Pkh<Pk>), - Wpkh(Wpkh<Pk>), - Sh(Sh<Pk>), - Wsh(Wsh<Pk>), - Tr(Tr<Pk>), -}
Expand description

Script descriptor

-

Variants§

§

Bare(Bare<Pk>)

A raw scriptpubkey (including pay-to-pubkey) under Legacy context

-
§

Pkh(Pkh<Pk>)

Pay-to-PubKey-Hash

-
§

Wpkh(Wpkh<Pk>)

Pay-to-Witness-PubKey-Hash

-
§

Sh(Sh<Pk>)

Pay-to-ScriptHash(includes nested wsh/wpkh/sorted multi)

-
§

Wsh(Wsh<Pk>)

Pay-to-Witness-ScriptHash with Segwitv0 context

-
§

Tr(Tr<Pk>)

Pay-to-Taproot

-

Implementations§

Create a new pk descriptor

-

Create a new PkH descriptor

-

Create a new Wpkh descriptor -Will return Err if uncompressed key is used

-

Create a new sh wrapped wpkh from Pk. -Errors when uncompressed keys are supplied

-

Create a new sh for a given redeem script -Errors when miniscript exceeds resource limits under p2sh context -or does not type check at the top level

-

Create a new wsh descriptor from witness script -Errors when miniscript exceeds resource limits under p2sh context -or does not type check at the top level

-

Create a new sh wrapped wsh descriptor with witness script -Errors when miniscript exceeds resource limits under wsh context -or does not type check at the top level

-

Create a new bare descriptor from witness script -Errors when miniscript exceeds resource limits under bare context -or does not type check at the top level

-

Create a new sh wrapper for the given wpkh descriptor

-

Create a new sh wrapper for the given wsh descriptor

-

Create a new sh sortedmulti descriptor with threshold k -and Vec of pks. -Errors when miniscript exceeds resource limits under p2sh context

-

Create a new sh wrapped wsh sortedmulti descriptor from threshold -k and Vec of pks -Errors when miniscript exceeds resource limits under segwit context

-

Create a new wsh sorted multi descriptor -Errors when miniscript exceeds resource limits under p2sh context

-

Create new tr descriptor -Errors when miniscript exceeds resource limits under Tap context

-

Get the [DescriptorType] of Descriptor

-

Checks whether the descriptor is safe.

-

Checks whether all the spend paths in the descriptor are possible on the -bitcoin network under the current standardness and consensus rules. Also -checks whether the descriptor requires signatures on all spend paths and -whether the script is malleable.

-

In general, all the guarantees of miniscript hold only for safe scripts. -The signer may not be able to find satisfactions even if one exists.

-

Computes an upper bound on the difference between a non-satisfied -TxIn’s segwit_weight and a satisfied TxIn’s segwit_weight

-

Since this method uses segwit_weight instead of legacy_weight, -if you want to include only legacy inputs in your transaction, -you should remove 1WU from each input’s max_weight_to_satisfy -for a more accurate estimate.

-

In other words, for segwit inputs or legacy inputs included in -segwit transactions, the following will hold for each input if -that input was satisfied with the largest possible witness:

- -
ⓘ
for i in 0..transaction.input.len() {
-    assert_eq!(
-        descriptor_for_input[i].max_weight_to_satisfy(),
-        transaction.input[i].segwit_weight() - TxIn::default().segwit_weight()
-    );
-}
-

Instead, for legacy transactions, the following will hold for each input -if that input was satisfied with the largest possible witness:

- -
ⓘ
for i in 0..transaction.input.len() {
-    assert_eq!(
-        descriptor_for_input[i].max_weight_to_satisfy(),
-        transaction.input[i].legacy_weight() - TxIn::default().legacy_weight()
-    );
-}
-

Assumes all ECDSA signatures are 73 bytes, including push opcode and -sighash suffix. -Assumes all Schnorr signatures are 66 bytes, including push opcode and -sighash suffix.

-
Errors
-

When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).

-
👎Deprecated: use max_weight_to_satisfy instead

Computes an upper bound on the weight of a satisfying witness to the -transaction.

-

Assumes all ec-signatures are 73 bytes, including push opcode and -sighash suffix. Includes the weight of the VarInts encoding the -scriptSig and witness stack length.

-
Errors
-

When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).

-

Computes the Bitcoin address of the descriptor, if one exists

-

Some descriptors like pk() don’t have an address.

-
Errors
-

For raw/bare descriptors that don’t have an address.

-

Computes the scriptpubkey of the descriptor.

-

Computes the scriptSig that will be in place for an unsigned input -spending an output with this descriptor. For pre-segwit descriptors, -which use the scriptSig for signatures, this returns the empty script.

-

This is used in Segwit transactions to produce an unsigned transaction -whose txid will not change during signing (since only the witness data -will change).

-

Computes the the underlying script before any hashing is done. For -Bare, Pkh and Wpkh this is the scriptPubkey; for ShWpkh and Sh -this is the redeemScript; for the others it is the witness script.

-
Errors
-

If the descriptor is a taproot descriptor.

-

Computes the scriptCode of a transaction output.

-

The scriptCode is the Script of the previous transaction output being -serialized in the sighash when evaluating a CHECKSIG & co. OP code.

-
Errors
-

If the descriptor is a taproot descriptor.

-

Returns satisfying non-malleable witness and scriptSig to spend an -output controlled by the given descriptor if it possible to -construct one using the satisfier S.

-

Returns a possilbly mallable satisfying non-malleable witness and scriptSig to spend an -output controlled by the given descriptor if it possible to -construct one using the satisfier S.

-

Attempts to produce a non-malleable satisfying witness and scriptSig to spend an -output controlled by the given descriptor; add the data to a given -TxIn output.

-

Returns a plan if the provided assets are sufficient to produce a non-malleable satisfaction

-

If the assets aren’t sufficient for generating a Plan, the descriptor is returned

-

Returns a plan if the provided assets are sufficient to produce a malleable satisfaction

-

If the assets aren’t sufficient for generating a Plan, the descriptor is returned

-
👎Deprecated: use has_wildcards instead

Whether or not the descriptor has any wildcards

-

Whether or not the descriptor has any wildcards i.e. /*.

-

Replaces all wildcards (i.e. /*) in the descriptor with a particular derivation index, -turning it into a definite descriptor.

-
Errors
-
    -
  • If index ≥ 2^31
  • -
-
👎Deprecated: use at_derivation_index instead

Deprecated name for Self::at_derivation_index.

-

Convert all the public keys in the descriptor to [bitcoin::PublicKey] by deriving them or -otherwise converting them. All [bitcoin::secp256k1::XOnlyPublicKey]s are converted to by adding a -default(0x02) y-coordinate.

-

This is a shorthand for:

- -
    .expect("Valid ranged descriptor");
-let derived_descriptor = descriptor.at_derivation_index(index).unwrap().derived_descriptor(&secp).unwrap();
-

and is only here really here for backwards compatbility. -See at_derivation_index and [derived_descriptor] for more documentation.

-
Errors
-

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

-

Parse a descriptor that may contain secret keys

-

Internally turns every secret key found into the corresponding public key and then returns a -a descriptor that only contains public keys and a map to lookup the secret key given a public key.

-

Serialize a descriptor to string with its secret keys

-

Utility method for deriving the descriptor at each index in a range to find one matching -script_pubkey.

-

If it finds a match then it returns the index it was derived at and the concrete -descriptor at that index. If the descriptor is non-derivable then it will simply check the -script pubkey against the descriptor and return it if it matches (in this case the index -returned will be meaningless).

-

Whether this descriptor contains a key that has multiple derivation paths.

-

Get as many descriptors as different paths in this descriptor.

-

For multipath descriptors it will return as many descriptors as there is -“parallel” paths. For regular descriptors it will just return itself.

-

Convert all the public keys in the descriptor to [bitcoin::PublicKey] by deriving them or -otherwise converting them. All [bitcoin::secp256k1::XOnlyPublicKey]s are converted to by adding a -default(0x02) y-coordinate.

-
Examples
-
use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
-use miniscript::bitcoin::secp256k1;
-use std::str::FromStr;
-
-// test from bip 86
-let secp = secp256k1::Secp256k1::verification_only();
-let descriptor = Descriptor::<DescriptorPublicKey>::from_str("tr(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)")
-    .expect("Valid ranged descriptor");
-let result = descriptor.at_derivation_index(0).unwrap().derived_descriptor(&secp).expect("Non-hardened derivation");
-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
Returns the minimum value (in satoshis) at which an output is broadcastable. -Panics if the descriptor wildcard is hardened. Read more
Returns the descriptor id, calculated as the sha256 of the descriptor, checksum not -included. 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
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
Converts this 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.

-

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/descriptor/enum.DescriptorPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.DescriptorPublicKey.html deleted file mode 100644 index 34ebd7dbcf..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.DescriptorPublicKey.html +++ /dev/null @@ -1,55 +0,0 @@ -DescriptorPublicKey in bdk::descriptor - Rust
pub enum DescriptorPublicKey {
-    Single(SinglePub),
-    XPub(DescriptorXKey<Xpub>),
-    MultiXPub(DescriptorMultiXKey<Xpub>),
-}
Expand description

The descriptor pubkey, either a single pubkey or an xpub.

-

Variants§

§

Single(SinglePub)

Single public key.

-
§

XPub(DescriptorXKey<Xpub>)

Extended public key (xpub).

-
§

MultiXPub(DescriptorMultiXKey<Xpub>)

Multiple extended public keys.

-

Implementations§

The fingerprint of the master key associated with this key, 0x00000000 if none.

-

Full path, from the master key

-

For wildcard keys this will return the path up to the wildcard, so you -can get full paths by appending one additional derivation step, according -to the wildcard type (hardened or normal).

-

For multipath extended keys, this returns None.

-

Returns a vector containing the full derivation paths from the master key. -The vector will contain just one element for single keys, and multiple elements -for multipath extended keys.

-

For wildcard keys this will return the path up to the wildcard, so you -can get full paths by appending one additional derivation step, according -to the wildcard type (hardened or normal).

-
👎Deprecated: use has_wildcard instead

Whether or not the key has a wildcard

-

Whether or not the key has a wildcard

-
👎Deprecated: use at_derivation_index instead

Deprecated name for Self::at_derivation_index.

-

Replaces any wildcard (i.e. /*) in the key with a particular derivation index, turning it into a -definite key (i.e. one where all the derivation paths are set).

-
Returns
-
    -
  • If this key is not an xpub, returns self.
  • -
  • If this key is an xpub but does not have a wildcard, returns self.
  • -
  • Otherwise, returns the xpub at derivation index (removing the wildcard).
  • -
-
Errors
-
    -
  • If index is hardened.
  • -
-

Whether or not this key has multiple derivation paths.

-

Get as many keys as derivation paths in this key.

-

For raw public key and single-path extended keys it will return the key itself. -For multipath extended keys it will return a single-path extended key per derivation -path.

-

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
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
Convert self into a Assets struct
Turn the key into a DescriptorKey within the requested ScriptContext
The associated [bitcoin::hashes::sha256::Hash] for this [MiniscriptKey], used in the -sha256 fragment. Read more
The associated [miniscript::hash256::Hash] for this [MiniscriptKey], used in the -hash256 fragment. Read more
The associated [bitcoin::hashes::ripemd160::Hash] for this [MiniscriptKey] type, used -in the ripemd160 fragment. Read more
The associated [bitcoin::hashes::hash160::Hash] for this [MiniscriptKey] type, used in -the hash160 fragment. Read more
Returns true if the pubkey is uncompressed. Defaults to false.
Returns true if the pubkey is an x-only pubkey. Defaults to false.
Returns the number of different derivation paths in this key. Only >1 for keys -in BIP389 multipath descriptors. 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/descriptor/enum.Legacy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html deleted file mode 100644 index 75d2b71c92..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html +++ /dev/null @@ -1,54 +0,0 @@ -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

-

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 <= -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 consensus key associated with the type. Must be a parseable key
Depending on ScriptContext, fragments can be malleable. For Example, -under Legacy context, PkH is malleable because it is possible to -estimate the cost of satisfaction because of compressed keys -This is currently only used in compiler code for removing malleable -compilations. -This does NOT recursively check if the children of the fragment are -valid or not. Since the compilation proceeds in a leaf to root fashion, -a recursive check is unnecessary. Read more
Each context has slightly different rules on what Pks are allowed in descriptors -Legacy/Bare does not allow x_only keys -Segwit does not allow uncompressed keys and x_only keys -Tapscript does not allow uncompressed keys Read more
Check whether the given satisfaction is valid under the ScriptContext -For example, segwit satisfactions may fail if the witness len is more -3600 or number of stack elements are more than 100. Read more
Depending on script Context, some of the Terminals might not -be valid under the current consensus rules. -Or some of the script resource limits may have been exceeded. -These miniscripts would never be accepted by the Bitcoin network and hence -it is safe to discard them -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -uncompressed public keys are non-standard and thus invalid. -In LegacyP2SH context, scripts above 520 bytes are invalid. -Post Tapscript upgrade, this would have to consider other nodes. -This does NOT recursively check the miniscript fragments. Read more
Consensus rules at the Miniscript satisfaction time. -It is possible that some paths of miniscript may exceed resource limits -and our current satisfier and lifting analysis would not work correctly. -For example, satisfaction path(Legacy/Segwitv0) may require more than 201 opcodes. Read more
Policy rules at the Miniscript satisfaction time. -It is possible that some paths of miniscript may exceed resource limits -and our current satisfier and lifting analysis would not work correctly. -For example, satisfaction path in Legacy context scriptSig more -than 1650 bytes Read more
Depending on script context, the size of a satifaction witness may slightly differ.
Get the len of public key when serialized based on context -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
Depending on script Context, some of the script resource limits -may have been exceeded under the current bitcoin core policy rules -These miniscripts would never be accepted by the Bitcoin network and hence -it is safe to discard them. (unless explicitly disabled by non-standard flag) -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -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.

-

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/descriptor/enum.Segwitv0.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html deleted file mode 100644 index 5e88ba8fd2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html +++ /dev/null @@ -1,51 +0,0 @@ -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 <= -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 consensus key associated with the type. Must be a parseable key
Depending on ScriptContext, fragments can be malleable. For Example, -under Legacy context, PkH is malleable because it is possible to -estimate the cost of satisfaction because of compressed keys -This is currently only used in compiler code for removing malleable -compilations. -This does NOT recursively check if the children of the fragment are -valid or not. Since the compilation proceeds in a leaf to root fashion, -a recursive check is unnecessary. Read more
Each context has slightly different rules on what Pks are allowed in descriptors -Legacy/Bare does not allow x_only keys -Segwit does not allow uncompressed keys and x_only keys -Tapscript does not allow uncompressed keys Read more
Check whether the given satisfaction is valid under the ScriptContext -For example, segwit satisfactions may fail if the witness len is more -3600 or number of stack elements are more than 100. Read more
Depending on script Context, some of the Terminals might not -be valid under the current consensus rules. -Or some of the script resource limits may have been exceeded. -These miniscripts would never be accepted by the Bitcoin network and hence -it is safe to discard them -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -uncompressed public keys are non-standard and thus invalid. -In LegacyP2SH context, scripts above 520 bytes are invalid. -Post Tapscript upgrade, this would have to consider other nodes. -This does NOT recursively check the miniscript fragments. Read more
Consensus rules at the Miniscript satisfaction time. -It is possible that some paths of miniscript may exceed resource limits -and our current satisfier and lifting analysis would not work correctly. -For example, satisfaction path(Legacy/Segwitv0) may require more than 201 opcodes. Read more
Depending on script Context, some of the script resource limits -may have been exceeded under the current bitcoin core policy rules -These miniscripts would never be accepted by the Bitcoin network and hence -it is safe to discard them. (unless explicitly disabled by non-standard flag) -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -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
Policy rules at the Miniscript satisfaction time. -It is possible that some paths of miniscript may exceed resource limits -and our current satisfier and lifting analysis would not work correctly. -For example, satisfaction path in Legacy context scriptSig more -than 1650 bytes Read more
Depending on script context, the size of a satifaction witness may slightly differ.
Get the len of public key when serialized based on context -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.

-

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/descriptor/error/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/enum.Error.html deleted file mode 100644 index f007504c50..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/enum.Error.html +++ /dev/null @@ -1,33 +0,0 @@ -Error in bdk::descriptor::error - Rust

Enum bdk::descriptor::error::Error

source ·
pub enum Error {
-    InvalidHdKeyPath,
-    InvalidDescriptorChecksum,
-    HardenedDerivationXpub,
-    MultiPath,
-    Key(KeyError),
-    Policy(PolicyError),
-    InvalidDescriptorCharacter(u8),
-    Bip32(Error),
-    Base58(Error),
-    Pk(Error),
-    Miniscript(Error),
-    Hex(HexToBytesError),
-}
Expand description

Errors related to the parsing and usage of descriptors

-

Variants§

§

InvalidHdKeyPath

Invalid HD Key path, such as having a wildcard but a length != 1

-
§

InvalidDescriptorChecksum

The provided descriptor doesn’t match its checksum

-
§

HardenedDerivationXpub

The descriptor contains hardened derivation steps on public extended keys

-
§

MultiPath

The descriptor contains multipath keys

-
§

Key(KeyError)

Error thrown while working with keys

-
§

Policy(PolicyError)

Error while extracting and manipulating policies

-
§

InvalidDescriptorCharacter(u8)

Invalid byte found in the descriptor checksum

-
§

Bip32(Error)

BIP32 error

-
§

Base58(Error)

Error during base58 decoding

-
§

Pk(Error)

Key-related error

-
§

Miniscript(Error)

Miniscript error

-
§

Hex(HexToBytesError)

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.

-

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/descriptor/error/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/index.html deleted file mode 100644 index be67e9f2eb..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/index.html +++ /dev/null @@ -1,3 +0,0 @@ -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/error/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/sidebar-items.js deleted file mode 100644 index eb47e2c4d1..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["Error","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 deleted file mode 100644 index ce749653c9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/index.html +++ /dev/null @@ -1,13 +0,0 @@ -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

The top-level miniscript abstract syntax tree (AST).

Enums

Script descriptor
The descriptor pubkey, either a single pubkey or an xpub.
Legacy ScriptContext -To be used as P2SH scripts -For creation of Bare scriptpubkeys, construct the Miniscript -under Bare ScriptContext
Segwitv0 ScriptContext

Traits

Trait implemented on Descriptors to add a method to extract the spending policy
Trait for types which can be converted into an ExtendedDescriptor and a KeyMap usable by a wallet in a specific [Network]
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 Definitions

Alias for a Descriptor that contains extended derived keys
Alias for a Descriptor that can contain extended keys using DescriptorPublicKey
Alias for the type of maps that represent derivation paths in a psbt::Input or -psbt::Output
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/descriptor/policy/enum.BuildSatisfaction.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html deleted file mode 100644 index e5b194d7f2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html +++ /dev/null @@ -1,22 +0,0 @@ -BuildSatisfaction in bdk::descriptor::policy - Rust
pub enum BuildSatisfaction<'a> {
-    None,
-    Psbt(&'a Psbt),
-    PsbtTimelocks {
-        psbt: &'a Psbt,
-        current_height: u32,
-        input_max_height: u32,
-    },
-}
Expand description

Options to build the satisfaction field in the policy

-

Variants§

§

None

Don’t generate satisfaction field

-
§

Psbt(&'a Psbt)

Analyze the given PSBT to check for existing signatures

-
§

PsbtTimelocks

Fields

§psbt: &'a Psbt

Given PSBT

-
§current_height: u32

Current blockchain height

-
§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.

-

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/descriptor/policy/enum.PkOrF.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PkOrF.html deleted file mode 100644 index 15fc5513c2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PkOrF.html +++ /dev/null @@ -1,16 +0,0 @@ -PkOrF in bdk::descriptor::policy - Rust

Enum bdk::descriptor::policy::PkOrF

source ·
pub enum PkOrF {
-    Pubkey(PublicKey),
-    XOnlyPubkey(XOnlyPublicKey),
-    Fingerprint(Fingerprint),
-}
Expand description

A unique identifier for a key

-

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 -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/descriptor/policy/enum.PolicyError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html deleted file mode 100644 index cb547c08e6..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html +++ /dev/null @@ -1,23 +0,0 @@ -PolicyError in bdk::descriptor::policy - Rust
pub enum PolicyError {
-    NotEnoughItemsSelected(String),
-    IndexOutOfRange(usize),
-    AddOnLeaf,
-    AddOnPartialComplete,
-    MixedTimelockUnits,
-    IncompatibleConditions,
-}
Expand description

Errors that can happen while extracting and manipulating policies

-

Variants§

§

NotEnoughItemsSelected(String)

Not enough items are selected to satisfy a SatisfiableItem::Thresh or a SatisfiableItem::Multisig

-
§

IndexOutOfRange(usize)

Index out of range for an item to satisfy a SatisfiableItem::Thresh or a SatisfiableItem::Multisig

-
§

AddOnLeaf

Can not add to an item that is Satisfaction::None or Satisfaction::Complete

-
§

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 -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
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 deleted file mode 100644 index 1b350a7034..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.Satisfaction.html +++ /dev/null @@ -1,44 +0,0 @@ -Satisfaction in bdk::descriptor::policy - Rust
pub enum Satisfaction {
-    Partial {
-        n: usize,
-        m: usize,
-        items: Vec<usize>,
-        sorted: Option<bool>,
-        conditions: ConditionMap,
-    },
-    PartialComplete {
-        n: usize,
-        m: usize,
-        items: Vec<usize>,
-        sorted: Option<bool>,
-        conditions: FoldedConditionMap,
-    },
-    Complete {
-        condition: Condition,
-    },
-    None,
-}
Expand description

Represent if and how much a policy item is satisfied by the wallet’s descriptor

-

Variants§

§

Partial

Fields

§n: usize

Total number of items

-
§m: usize

Threshold

-
§items: Vec<usize>

The items that can be satisfied by the descriptor or are satisfied in the PSBT

-
§sorted: Option<bool>

Whether the items are sorted in lexicographic order (used by sortedmulti)

-
§conditions: ConditionMap

Extra conditions that also need to be satisfied

-

Only a partial satisfaction of some kind of threshold policy

-
§

PartialComplete

Fields

§n: usize

Total number of items

-
§m: usize

Threshold

-
§items: Vec<usize>

The items that can be satisfied by the descriptor

-
§sorted: Option<bool>

Whether the items are sorted in lexicographic order (used by sortedmulti)

-
§conditions: FoldedConditionMap

Extra conditions that also need to be satisfied

-

Can reach the threshold of some kind of threshold policy

-
§

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 -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/descriptor/policy/enum.SatisfiableItem.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html deleted file mode 100644 index 4440b709be..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html +++ /dev/null @@ -1,60 +0,0 @@ -SatisfiableItem in bdk::descriptor::policy - Rust
pub enum SatisfiableItem {
-    EcdsaSignature(PkOrF),
-    SchnorrSignature(PkOrF),
-    Sha256Preimage {
-        hash: Hash,
-    },
-    Hash256Preimage {
-        hash: Hash,
-    },
-    Ripemd160Preimage {
-        hash: Hash,
-    },
-    Hash160Preimage {
-        hash: Hash,
-    },
-    AbsoluteTimelock {
-        value: LockTime,
-    },
-    RelativeTimelock {
-        value: Sequence,
-    },
-    Multisig {
-        keys: Vec<PkOrF>,
-        threshold: usize,
-    },
-    Thresh {
-        items: Vec<Policy>,
-        threshold: usize,
-    },
-}
Expand description

An item that needs to be satisfied

-

Variants§

§

EcdsaSignature(PkOrF)

ECDSA Signature for a raw public key

-
§

SchnorrSignature(PkOrF)

Schnorr Signature for a raw public key

-
§

Sha256Preimage

Fields

§hash: Hash

The digest value

-

SHA256 preimage hash

-
§

Hash256Preimage

Fields

§hash: Hash

The digest value

-

Double SHA256 preimage hash

-
§

Ripemd160Preimage

Fields

§hash: Hash

The digest value

-

RIPEMD160 preimage hash

-
§

Hash160Preimage

Fields

§hash: Hash

The digest value

-

SHA256 then RIPEMD160 preimage hash

-
§

AbsoluteTimelock

Fields

§value: LockTime

The timelock value

-

Absolute timeclock timestamp

-
§

RelativeTimelock

Fields

§value: Sequence

The timelock value

-

Relative timelock locktime

-
§

Multisig

Fields

§keys: Vec<PkOrF>

The raw public key or extended key fingerprint

-
§threshold: usize

The required threshold count

-

Multi-signature public keys with threshold count

-
§

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 -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/descriptor/policy/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/index.html deleted file mode 100644 index 4ee3bc3e36..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/index.html +++ /dev/null @@ -1,18 +0,0 @@ -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.

-

Example

-
use bdk::descriptor::policy::BuildSatisfaction;
-let secp = Secp256k1::new();
-let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
-
-let (extended_desc, key_map) = ExtendedDescriptor::parse_descriptor(&secp, desc)?;
-println!("{:?}", extended_desc);
-
-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).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/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/sidebar-items.js deleted file mode 100644 index 0b375ed6fb..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["BuildSatisfaction","Options to build the satisfaction field in the policy"],["PkOrF","A unique identifier for a key"],["PolicyError","Errors that can happen while extracting and manipulating policies"],["Satisfaction","Represent if and how much a policy item is satisfied by the wallet’s descriptor"],["SatisfiableItem","An item that needs to be satisfied"]],"struct":[["Condition","An extra condition that must be satisfied but that is out of control of the user TODO: use `bitcoin::LockTime` and `bitcoin::Sequence`"],["Policy","Descriptor spending policy"]],"type":[["ConditionMap","Type for a map of sets of [`Condition`] items keyed by each set’s index"],["FoldedConditionMap","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 deleted file mode 100644 index 93e96a8f81..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Condition.html +++ /dev/null @@ -1,18 +0,0 @@ -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 -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/descriptor/policy/struct.Policy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Policy.html deleted file mode 100644 index 2357779d49..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Policy.html +++ /dev/null @@ -1,25 +0,0 @@ -Policy in bdk::descriptor::policy - Rust

Struct bdk::descriptor::policy::Policy

source ·
pub struct Policy {
-    pub id: String,
-    pub item: SatisfiableItem,
-    pub satisfaction: Satisfaction,
-    pub contribution: Satisfaction,
-}
Expand description

Descriptor spending policy

-

Fields§

§id: String

Identifier for this policy node

-
§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 -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 -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 -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/descriptor/policy/type.ConditionMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.ConditionMap.html deleted file mode 100644 index de202410d3..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.ConditionMap.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index b5805eaf06..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.FoldedConditionMap.html +++ /dev/null @@ -1,3 +0,0 @@ -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/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/sidebar-items.js deleted file mode 100644 index d738efbc83..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["Descriptor","Script descriptor"],["DescriptorPublicKey","The descriptor pubkey, either a single pubkey or an xpub."],["Legacy","Legacy ScriptContext To be used as P2SH scripts For creation of Bare scriptpubkeys, construct the Miniscript under `Bare` ScriptContext"],["Segwitv0","Segwitv0 ScriptContext"]],"mod":[["checksum","Descriptor checksum"],["error","Descriptor errors"],["policy","Descriptor policy"],["template","Descriptor templates"]],"struct":[["Miniscript","The top-level miniscript abstract syntax tree (AST)."]],"trait":[["ExtractPolicy","Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]"],["IntoWalletDescriptor","Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]"],["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":[["DerivedDescriptor","Alias for a [`Descriptor`] that contains extended derived keys"],["ExtendedDescriptor","Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]"],["HdKeyPaths","Alias for the type of maps that represent derivation paths in a `psbt::Input` or `psbt::Output`"],["TapKeyOrigins","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/descriptor/struct.Miniscript.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.Miniscript.html deleted file mode 100644 index f1db40d864..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.Miniscript.html +++ /dev/null @@ -1,166 +0,0 @@ -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, - /* private fields */ -}
Expand description

The top-level miniscript abstract syntax tree (AST).

-

Fields§

§node: Terminal<Pk, Ctx>

A node in the AST.

-
§ty: Type

The correctness and malleability type information for the AST node.

-
§ext: ExtData

Additional information helpful for extra analysis.

-

Implementations§

Whether all spend paths of miniscript require a signature

-

Whether the miniscript is malleable

-

Whether the miniscript can exceed the resource limits(Opcodes, Stack limit etc)

-

Whether the miniscript contains a combination of timelocks

-

Whether the miniscript has repeated Pk or Pkh

-

Whether the given miniscript contains a raw pkh fragment

-

Check whether the underlying Miniscript is safe under the current context -Lifting these polices would create a semantic representation that does -not represent the underlying semantics when miniscript is spent. -Signing logic may not find satisfaction even if one exists.

-

For most cases, users should be dealing with safe scripts. -Use this function to check whether the guarantees of library hold. -Most functions of the library like would still -work, but results cannot be relied upon

-

Check whether the miniscript follows the given Extra policy [ExtParams]

-

Iterator-related extensions for Miniscript

-

Creates a new [Iter] iterator that will iterate over all Miniscript items within -AST by traversing its branches. For the specific algorithm please see -[Iter::next] function.

-

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 -them.

-

Returns child node with given index, if any

-

Returns Option::Some with cloned n’th public key from the current miniscript item, -if any. Otherwise returns Option::None.

-

NB: The function analyzes only single miniscript item and not any of its descendants in AST.

-

Add type information(Type and Extdata) to Miniscript based on -AstElem fragment. Dependent on display and clone because of Error -Display code of type_check.

-

Create a new Miniscript from a Terminal node and a Type annotation -This does not check the typing rules. The user is responsible for ensuring -that the type provided is correct.

-

You should almost always use Miniscript::from_ast instead of this function.

-

Extracts the AstElem representing the root of the miniscript

-

Get a reference to the inner AstElem representing the root of miniscript

-

Encode as a Bitcoin script

-

Size, in bytes of the script-pubkey. If this Miniscript is used outside -of segwit (e.g. in a bare or P2SH descriptor), this quantity should be -multiplied by 4 to compute the weight.

-

In general, it is not recommended to use this function directly, but -to instead call the corresponding function on a Descriptor, which -will handle the segwit/non-segwit technicalities for you.

-

Maximum number of witness elements used to satisfy the Miniscript -fragment, including the witness script itself. Used to estimate -the weight of the VarInt that specifies this number in a serialized -transaction.

-

This function may returns Error when the Miniscript is -impossible to satisfy

-

Maximum size, in bytes, of a satisfying witness. For Segwit outputs -one_cost should be set to 2, since the number 1 requires two -bytes to encode. For non-segwit outputs one_cost should be set to -1, since OP_1 is available in scriptSigs.

-

In general, it is not recommended to use this function directly, but -to instead call the corresponding function on a Descriptor, which -will handle the segwit/non-segwit technicalities for you.

-

All signatures are assumed to be 73 bytes in size, including the -length prefix (segwit) or push opcode (pre-segwit) and sighash -postfix.

-

Attempt to produce non-malleable satisfying witness for the -witness script represented by the parse tree

-

Attempt to produce a malleable satisfying witness for the -witness script represented by the parse tree

-

Attempt to produce a non-malleable witness template given the assets available

-

Attempt to produce a malleable witness template given the assets available

-

Attempt to parse an insane(scripts don’t clear sanity checks) -script into a Miniscript representation. -Use this to parse scripts with repeated pubkeys, timelock mixing, malleable -scripts without sig or scripts that can exceed resource limits. -Some of the analysis guarantees of miniscript are lost when dealing with -insane scripts. In general, in a multi-party setting users should only -accept sane scripts.

-

Attempt to parse an miniscript with extra features that not yet specified in the spec. -Users should not use this function unless they scripts can/will change in the future. -Currently, this function supports the following features: -- Parsing all insane scripts -- Parsing miniscripts with raw pubkey hashes

-

Allowed extra features can be specified by the ext [ExtParams] argument.

-

Attempt to parse a Script into Miniscript representation.

-

This function will fail parsing for scripts that do not clear the -Miniscript::sanity_check checks. Use Miniscript::parse_insane to -parse such scripts.

-
Decode/Parse a miniscript from script hex
-
use miniscript::{Miniscript, Segwitv0, Tap};
-use miniscript::bitcoin::secp256k1::XOnlyPublicKey;
-use miniscript::bitcoin::hashes::hex::FromHex;
-
-type Segwitv0Script = Miniscript<bitcoin::PublicKey, Segwitv0>;
-type TapScript = Miniscript<XOnlyPublicKey, Tap>;
-
-// parse x-only miniscript in Taproot context
-let tapscript_ms = TapScript::parse(&bitcoin::ScriptBuf::from_hex(
-    "202788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
-).expect("Even length hex"))
-    .expect("Xonly keys are valid only in taproot context");
-// tapscript fails decoding when we use them with compressed keys
-let err = TapScript::parse(&bitcoin::ScriptBuf::from_hex(
-    "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
-).expect("Even length hex"))
-    .expect_err("Compressed keys cannot be used in Taproot context");
-// Segwitv0 succeeds decoding with full keys.
-Segwitv0Script::parse(&bitcoin::ScriptBuf::from_hex(
-    "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
-).expect("Even length hex"))
-    .expect("Compressed keys are allowed in Segwit context");
-
-

Substitutes raw public keys hashes with the public keys as provided by map.

-

Attempt to parse an insane(scripts don’t clear sanity checks) -from string into a Miniscript representation. -Use this to parse scripts with repeated pubkeys, timelock mixing, malleable -scripts without sig or scripts that can exceed resource limits. -Some of the analysis guarantees of miniscript are lost when dealing with -insane scripts. In general, in a multi-party setting users should only -accept sane scripts.

-

Attempt to parse an Miniscripts that don’t follow the spec. -Use this to parse scripts with repeated pubkeys, timelock mixing, malleable -scripts, raw pubkey hashes without sig or scripts that can exceed resource limits.

-

Use [ExtParams] builder to specify the types of non-sane rules to allow while parsing.

-

Lifting corresponds to conversion of a miniscript into a [Semantic] -policy for human readable or machine analysis. However, naively lifting -miniscripts can result in incorrect interpretations that don’t -correspond to the underlying semantics when we try to spend them on -bitcoin network. This can occur if the miniscript contains:

-
    -
  1. A combination of timelocks
  2. -
  3. A spend that exceeds resource limits
  4. -
-

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 -do not clear the Miniscript::sanity_check checks.

-
The associated error which can be returned from parsing.

Parse an expression tree into a Miniscript. As a general rule, this -should not be called directly; rather go through the descriptor API.

-

Hash of Miniscript must depend only on node and not the type information.

-

The type information and extra properties are implied by the AST.

-
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
Converts this object into an abstract policy.

Ord of Miniscript must depend only on node and not the type information.

-

The type information and extra properties are implied by the AST.

-
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

PartialEq of Miniscript must depend only on node and not the type information.

-

The type information and extra properties are implied by the AST.

-
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

PartialOrd of Miniscript must depend only on node and not the type information.

-

The type information and extra properties are implied 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 -for Pk is provided by [Translator]

-
The associated output type. This must be Self<Q>.
Interpret the node as an abstract node.
Accessor for the number of children this node has.
Accessor for the nth child of the node, if a child with that index exists.
Obtains an iterator of all the nodes rooted at the node, in pre-order.
Obtains a verbose iterator of all the nodes rooted at the DAG, in pre-order. Read more
Obtains an iterator of all the nodes rooted at the DAG, in post order. Read more

Eq of Miniscript must depend only on node and not the type information.

-

The type information and extra properties are implied 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.

-

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/descriptor/template/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html deleted file mode 100644 index e2692ce4c5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html +++ /dev/null @@ -1,5 +0,0 @@ -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}/*)
BIP86 template. Expands to tr(key/86'/{0,1}'/0'/{0,1}/*)
BIP86 public template. Expands to tr(key/{0,1}/*)
P2PKH template. Expands to a descriptor pkh(key)
P2TR template. Expands to a descriptor tr(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/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/sidebar-items.js deleted file mode 100644 index c4c1d6d2c1..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"struct":[["Bip44","BIP44 template. Expands to `pkh(key/44'/{0,1}'/0'/{0,1}/*)`"],["Bip44Public","BIP44 public template. Expands to `pkh(key/{0,1}/*)`"],["Bip49","BIP49 template. Expands to `sh(wpkh(key/49'/{0,1}'/0'/{0,1}/*))`"],["Bip49Public","BIP49 public template. Expands to `sh(wpkh(key/{0,1}/*))`"],["Bip84","BIP84 template. Expands to `wpkh(key/84'/{0,1}'/0'/{0,1}/*)`"],["Bip84Public","BIP84 public template. Expands to `wpkh(key/{0,1}/*)`"],["Bip86","BIP86 template. Expands to `tr(key/86'/{0,1}'/0'/{0,1}/*)`"],["Bip86Public","BIP86 public template. Expands to `tr(key/{0,1}/*)`"],["P2Pkh","P2PKH template. Expands to a descriptor `pkh(key)`"],["P2TR","P2TR template. Expands to a descriptor `tr(key)`"],["P2Wpkh","P2WPKH template. Expands to a descriptor `wpkh(key)`"],["P2Wpkh_P2Sh","P2WPKH-P2SH template. Expands to a descriptor `sh(wpkh(key))`"]],"trait":[["DescriptorTemplate","Trait for descriptor templates that can be built into a full descriptor"]],"type":[["DescriptorTemplateOut","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 deleted file mode 100644 index c13617b1f9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44.html +++ /dev/null @@ -1,21 +0,0 @@ -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::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-let mut wallet = Wallet::new_no_persist(
-    Bip44(key.clone(), KeychainKind::External),
-    Some(Bip44(key, KeychainKind::Internal)),
-    Network::Testnet,
-)?;
-
-assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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 deleted file mode 100644 index 7a8a165a97..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44Public.html +++ /dev/null @@ -1,24 +0,0 @@ -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 -for the key.

-

Example

-
use bdk::template::Bip44Public;
-
-let key = bitcoin::bip32::Xpub::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
-let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-let mut wallet = Wallet::new_no_persist(
-    Bip44Public(key.clone(), fingerprint, KeychainKind::External),
-    Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
-    Network::Testnet,
-)?;
-
-assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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 deleted file mode 100644 index 97603d2107..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49.html +++ /dev/null @@ -1,21 +0,0 @@ -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::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-let mut wallet = Wallet::new_no_persist(
-    Bip49(key.clone(), KeychainKind::External),
-    Some(Bip49(key, KeychainKind::Internal)),
-    Network::Testnet,
-)?;
-
-assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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 deleted file mode 100644 index aea57b8d93..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49Public.html +++ /dev/null @@ -1,24 +0,0 @@ -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 -for the key.

-

Example

-
use bdk::template::Bip49Public;
-
-let key = bitcoin::bip32::Xpub::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
-let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-let mut wallet = Wallet::new_no_persist(
-    Bip49Public(key.clone(), fingerprint, KeychainKind::External),
-    Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
-    Network::Testnet,
-)?;
-
-assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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 deleted file mode 100644 index 1b57aede0b..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84.html +++ /dev/null @@ -1,21 +0,0 @@ -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::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-let mut wallet = Wallet::new_no_persist(
-    Bip84(key.clone(), KeychainKind::External),
-    Some(Bip84(key, KeychainKind::Internal)),
-    Network::Testnet,
-)?;
-
-assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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 deleted file mode 100644 index e99332bff5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84Public.html +++ /dev/null @@ -1,24 +0,0 @@ -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 -for the key.

-

Example

-
use bdk::template::Bip84Public;
-
-let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
-let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-let mut wallet = Wallet::new_no_persist(
-    Bip84Public(key.clone(), fingerprint, KeychainKind::External),
-    Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
-    Network::Testnet,
-)?;
-
-assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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.Bip86.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip86.html deleted file mode 100644 index e999faf5d1..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip86.html +++ /dev/null @@ -1,21 +0,0 @@ -Bip86 in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::Bip86

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

BIP86 template. Expands to tr(key/86'/{0,1}'/0'/{0,1}/*)

-

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

-

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

-

Example

-
use bdk::template::Bip86;
-
-let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-let mut wallet = Wallet::new_no_persist(
-    Bip86(key.clone(), KeychainKind::External),
-    Some(Bip86(key, KeychainKind::Internal)),
-    Network::Testnet,
-)?;
-
-assert_eq!(wallet.next_unused_address(KeychainKind::External)?.to_string(), "tb1p5unlj09djx8xsjwe97269kqtxqpwpu2epeskgqjfk4lnf69v4tnqpp35qu");
-assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDCiHofpEs47kx358bPdJmTZHmCDqQ8qw32upCSxHrSEdeeBs2T5Mq6QMB2ukeMqhNBiyhosBvJErteVhfURPGXPv3qLJPw5MVpHUewsbP2m/0/*)#dkgvr5hm");
-

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 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.Bip86Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip86Public.html deleted file mode 100644 index 27640f4f3c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip86Public.html +++ /dev/null @@ -1,24 +0,0 @@ -Bip86Public in bdk::descriptor::template - Rust
pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub Fingerprint, pub KeychainKind);
Expand description

BIP86 public template. Expands to tr(key/{0,1}/*)

-

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

-

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

-

See Bip86 for a template that does the full derivation, but requires private data -for the key.

-

Example

-
use bdk::template::Bip86Public;
-
-let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
-let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-let mut wallet = Wallet::new_no_persist(
-    Bip86Public(key.clone(), fingerprint, KeychainKind::External),
-    Some(Bip86Public(key, fingerprint, KeychainKind::Internal)),
-    Network::Testnet,
-)?;
-
-assert_eq!(wallet.next_unused_address(KeychainKind::External)?.to_string(), "tb1pwjp9f2k5n0xq73ecuu0c5njvgqr3vkh7yaylmpqvsuuaafymh0msvcmh37");
-assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#2p65srku");
-

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 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 deleted file mode 100644 index feae46e5f0..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Pkh.html +++ /dev/null @@ -1,20 +0,0 @@ -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 mut wallet = Wallet::new_no_persist(P2Pkh(key), None, Network::Testnet)?;
-
-assert_eq!(
-    wallet
-        .next_unused_address(KeychainKind::External)?
-        .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.

-

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 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.P2TR.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2TR.html deleted file mode 100644 index 7a147ebe3e..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2TR.html +++ /dev/null @@ -1,20 +0,0 @@ -P2TR in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::P2TR

source ·
pub struct P2TR<K: IntoDescriptorKey<Tap>>(pub K);
Expand description

P2TR template. Expands to a descriptor tr(key)

-

Example

-
use bdk::template::P2TR;
-
-let key =
-    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-let mut wallet = Wallet::new_no_persist(P2TR(key), None, Network::Testnet)?;
-
-assert_eq!(
-    wallet
-        .next_unused_address(KeychainKind::External)?
-        .to_string(),
-    "tb1pvjf9t34fznr53u5tqhejz4nr69luzkhlvsdsdfq9pglutrpve2xq7hps46"
-);
-

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 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 deleted file mode 100644 index 66ee56e310..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh.html +++ /dev/null @@ -1,20 +0,0 @@ -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;
-
-let key =
-    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-let mut wallet = Wallet::new_no_persist(P2Wpkh(key), None, Network::Testnet)?;
-
-assert_eq!(
-    wallet
-        .next_unused_address(KeychainKind::External)?
-        .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.

-

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 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 deleted file mode 100644 index 9e15d64bab..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh_P2Sh.html +++ /dev/null @@ -1,20 +0,0 @@ -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;
-
-let key =
-    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-let mut wallet = Wallet::new_no_persist(P2Wpkh_P2Sh(key), None, Network::Testnet)?;
-
-assert_eq!(
-    wallet
-        .next_unused_address(KeychainKind::External)?
-        .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.

-

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 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 deleted file mode 100644 index 326d5925c2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/trait.DescriptorTemplate.html +++ /dev/null @@ -1,22 +0,0 @@ -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 -passed directly to the Wallet constructor.

-

Example

-
use bdk::descriptor::error::Error as DescriptorError;
-use bdk::keys::{IntoDescriptorKey, KeyError};
-use bdk::miniscript::Legacy;
-use bdk::template::{DescriptorTemplate, DescriptorTemplateOut};
-use bitcoin::Network;
-
-struct MyP2PKH<K: IntoDescriptorKey<Legacy>>(K);
-
-impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        Ok(bdk::descriptor!(pkh(self.0))?)
-    }
-}
-

Required Methods§

Build the complete descriptor

-

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 deleted file mode 100644 index 0a154a4aa6..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/type.DescriptorTemplateOut.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index b778bdfac6..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ExtractPolicy.html +++ /dev/null @@ -1,6 +0,0 @@ -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 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 deleted file mode 100644 index 261edf5f68..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.IntoWalletDescriptor.html +++ /dev/null @@ -1,8 +0,0 @@ -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§

\ 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 deleted file mode 100644 index 30cc257ae3..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ScriptContext.html +++ /dev/null @@ -1,93 +0,0 @@ -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 16 methods fn check_terminal_non_malleable<Pk>(
        _frag: &Terminal<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
; - fn check_pk<Pk>(pk: &Pk) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
; - fn max_satisfaction_size<Pk>(ms: &Miniscript<Pk, Self>) -> Option<usize>
    where
        Pk: MiniscriptKey
; - fn sig_type() -> SigType; - fn pk_len<Pk>(pk: &Pk) -> usize
    where
        Pk: MiniscriptKey
; - fn name_str() -> &'static str; - - fn check_witness<Pk>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_global_consensus_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_global_policy_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_local_consensus_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_local_policy_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_global_validity<Pk>(
        ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_local_validity<Pk>(
        ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn top_level_type_check<Pk>(ms: &Miniscript<Pk, Self>) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, - { ... } - fn other_top_level_checks<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, - { ... } - fn top_level_checks<Pk>(ms: &Miniscript<Pk, Self>) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, - { ... } -
}
Expand description

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

-

Required Associated Types§

The consensus key associated with the type. Must be a parseable key

-

Required Methods§

Depending on ScriptContext, fragments can be malleable. For Example, -under Legacy context, PkH is malleable because it is possible to -estimate the cost of satisfaction because of compressed keys -This is currently only used in compiler code for removing malleable -compilations. -This does NOT recursively check if the children of the fragment are -valid or not. Since the compilation proceeds in a leaf to root fashion, -a recursive check is unnecessary.

-

Each context has slightly different rules on what Pks are allowed in descriptors -Legacy/Bare does not allow x_only keys -Segwit does not allow uncompressed keys and x_only keys -Tapscript does not allow uncompressed keys

-

Depending on script context, the size of a satifaction witness may slightly differ.

-

The type of signature required for satisfaction

-

Get the len of public key when serialized based on context -Note that this includes the serialization prefix. Returns -34/66 for Bare/Legacy based on key compressedness -34 for Segwitv0, 33 for Tap

-

Local helper function to display error messages with context

-

Provided Methods§

Check whether the given satisfaction is valid under the ScriptContext -For example, segwit satisfactions may fail if the witness len is more -3600 or number of stack elements are more than 100.

-

Depending on script Context, some of the Terminals might not -be valid under the current consensus rules. -Or some of the script resource limits may have been exceeded. -These miniscripts would never be accepted by the Bitcoin network and hence -it is safe to discard them -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -uncompressed public keys are non-standard and thus invalid. -In LegacyP2SH context, scripts above 520 bytes are invalid. -Post Tapscript upgrade, this would have to consider other nodes. -This does NOT recursively check the miniscript fragments.

-

Depending on script Context, some of the script resource limits -may have been exceeded under the current bitcoin core policy rules -These miniscripts would never be accepted by the Bitcoin network and hence -it is safe to discard them. (unless explicitly disabled by non-standard flag) -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -scripts over 3600 bytes are invalid. -Post Tapscript upgrade, this would have to consider other nodes. -This does NOT recursively check the miniscript fragments.

-

Consensus rules at the Miniscript satisfaction time. -It is possible that some paths of miniscript may exceed resource limits -and our current satisfier and lifting analysis would not work correctly. -For example, satisfaction path(Legacy/Segwitv0) may require more than 201 opcodes.

-

Policy rules at the Miniscript satisfaction time. -It is possible that some paths of miniscript may exceed resource limits -and our current satisfier and lifting analysis would not work correctly. -For example, satisfaction path in Legacy context scriptSig more -than 1650 bytes

-

Check the consensus + policy(if not disabled) rules that are not based -satisfaction

-

Check the consensus + policy(if not disabled) rules including the -ones for satisfaction

-

Check whether the top-level is type B

-

Other top level checks that are context specific

-

Check top level consensus rules.

-

Implementors§

\ No newline at end of file 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 deleted file mode 100644 index 752a6f46c3..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.DerivedDescriptor.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index c2115d8396..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.ExtendedDescriptor.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 8fc0e0562f..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.HdKeyPaths.html +++ /dev/null @@ -1,4 +0,0 @@ -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.TapKeyOrigins.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.TapKeyOrigins.html deleted file mode 100644 index 6385fba5cc..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.TapKeyOrigins.html +++ /dev/null @@ -1,4 +0,0 @@ -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.KeychainKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html deleted file mode 100644 index 7bd8f41ce6..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html +++ /dev/null @@ -1,17 +0,0 @@ -KeychainKind in bdk - Rust

Enum bdk::KeychainKind

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

Types of keychains

-

Variants§

§

External

External keychain, used for deriving recipient addresses.

-
§

Internal

Internal keychain, used for deriving change addresses.

-

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
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/enum.Utxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Utxo.html deleted file mode 100644 index 9613430f52..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Utxo.html +++ /dev/null @@ -1,24 +0,0 @@ -Utxo in bdk - Rust

Enum bdk::Utxo

source ·
pub enum Utxo {
-    Local(LocalOutput),
-    Foreign {
-        outpoint: OutPoint,
-        sequence: Option<Sequence>,
-        psbt_input: Box<Input>,
-    },
-}
Expand description

An unspent transaction output (UTXO).

-

Variants§

§

Local(LocalOutput)

A UTXO owned by the local wallet.

-
§

Foreign

Fields

§outpoint: OutPoint

The location of the output.

-
§sequence: Option<Sequence>

The nSequence value to set for this input.

-
§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

-

Get the sequence number if an explicit sequence number has to be set for this input.

-

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/fn.version.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/fn.version.html deleted file mode 100644 index e43ecd2063..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/fn.version.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 15fc7e6a1a..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/index.html +++ /dev/null @@ -1,170 +0,0 @@ -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.63.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 details about the API of Wallet see the module-level documentation.

-

Blockchain data

-

In order to get blockchain data for Wallet to consume, you should configure a client from -an available chain source. Typically you make a request to the chain source and get a response -that the Wallet can use to update its view of the chain.

-

Blockchain Data Sources

-
    -
  • bdk_esplora: Grabs blockchain data from Esplora for updating BDK structures.
  • -
  • bdk_electrum: Grabs blockchain data from Electrum for updating BDK structures.
  • -
  • bdk_bitcoind_rpc: Grabs blockchain data from Bitcoin Core for updating BDK structures.
  • -
-

Examples

- -

Persistence

-

To persist the Wallet on disk, it must be constructed with a PersistBackend implementation.

-

Implementations

- -

Example

- - -
ⓘ
use bdk::{bitcoin::Network, wallet::{ChangeSet, Wallet}};
-
-fn main() {
-    // Create a new file `Store`.
-    let db = bdk_file_store::Store::<ChangeSet>::open_or_create_new(b"magic_bytes", "path/to/my_wallet.db").expect("create store");
-
-    let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
-    let mut wallet = Wallet::new_or_load(descriptor, None, db, Network::Testnet).expect("create or load wallet");
-
-    // Insert a single `TxOut` at `OutPoint` into the wallet.
-    let _ = wallet.insert_txout(outpoint, txout);
-    wallet.commit().expect("must write to database");
-}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Testing

Unit testing

cargo test
-

License

-

Licensed under either of

- -

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 Psbt structure.
Wallet

Macros

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

Structs

An unspent output owned by a Wallet.
A Utxo with its satisfaction_weight.

Enums

Types of keychains
An unspent transaction output (UTXO).

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/enum.DescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html deleted file mode 100644 index 295e22111d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html +++ /dev/null @@ -1,13 +0,0 @@ -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.

-

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/keys/enum.DescriptorPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html deleted file mode 100644 index 1eb04fb306..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html +++ /dev/null @@ -1,55 +0,0 @@ -DescriptorPublicKey in bdk::keys - Rust
pub enum DescriptorPublicKey {
-    Single(SinglePub),
-    XPub(DescriptorXKey<Xpub>),
-    MultiXPub(DescriptorMultiXKey<Xpub>),
-}
Expand description

The descriptor pubkey, either a single pubkey or an xpub.

-

Variants§

§

Single(SinglePub)

Single public key.

-
§

XPub(DescriptorXKey<Xpub>)

Extended public key (xpub).

-
§

MultiXPub(DescriptorMultiXKey<Xpub>)

Multiple extended public keys.

-

Implementations§

The fingerprint of the master key associated with this key, 0x00000000 if none.

-

Full path, from the master key

-

For wildcard keys this will return the path up to the wildcard, so you -can get full paths by appending one additional derivation step, according -to the wildcard type (hardened or normal).

-

For multipath extended keys, this returns None.

-

Returns a vector containing the full derivation paths from the master key. -The vector will contain just one element for single keys, and multiple elements -for multipath extended keys.

-

For wildcard keys this will return the path up to the wildcard, so you -can get full paths by appending one additional derivation step, according -to the wildcard type (hardened or normal).

-
👎Deprecated: use has_wildcard instead

Whether or not the key has a wildcard

-

Whether or not the key has a wildcard

-
👎Deprecated: use at_derivation_index instead

Deprecated name for Self::at_derivation_index.

-

Replaces any wildcard (i.e. /*) in the key with a particular derivation index, turning it into a -definite key (i.e. one where all the derivation paths are set).

-
Returns
-
    -
  • If this key is not an xpub, returns self.
  • -
  • If this key is an xpub but does not have a wildcard, returns self.
  • -
  • Otherwise, returns the xpub at derivation index (removing the wildcard).
  • -
-
Errors
-
    -
  • If index is hardened.
  • -
-

Whether or not this key has multiple derivation paths.

-

Get as many keys as derivation paths in this key.

-

For raw public key and single-path extended keys it will return the key itself. -For multipath extended keys it will return a single-path extended key per derivation -path.

-

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
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
Convert self into a Assets struct
Turn the key into a DescriptorKey within the requested ScriptContext
The associated [bitcoin::hashes::sha256::Hash] for this [MiniscriptKey], used in the -sha256 fragment. Read more
The associated [miniscript::hash256::Hash] for this [MiniscriptKey], used in the -hash256 fragment. Read more
The associated [bitcoin::hashes::ripemd160::Hash] for this [MiniscriptKey] type, used -in the ripemd160 fragment. Read more
The associated [bitcoin::hashes::hash160::Hash] for this [MiniscriptKey] type, used in -the hash160 fragment. Read more
Returns true if the pubkey is uncompressed. Defaults to false.
Returns true if the pubkey is an x-only pubkey. Defaults to false.
Returns the number of different derivation paths in this key. Only >1 for keys -in BIP389 multipath descriptors. 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/keys/enum.DescriptorSecretKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html deleted file mode 100644 index fbcfb1bc0d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html +++ /dev/null @@ -1,27 +0,0 @@ -DescriptorSecretKey in bdk::keys - Rust
pub enum DescriptorSecretKey {
-    Single(SinglePriv),
-    XPrv(DescriptorXKey<Xpriv>),
-    MultiXPrv(DescriptorMultiXKey<Xpriv>),
-}
Expand description

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

-

Variants§

§

Single(SinglePriv)

Single private key.

-
§

XPrv(DescriptorXKey<Xpriv>)

Extended private key (xpriv).

-
§

MultiXPrv(DescriptorMultiXKey<Xpriv>)

Multiple extended private keys.

-

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.

-

It will return an error if the key is a “multi-xpriv”, as we wouldn’t -always be able to apply hardened derivation steps if there are multiple -paths.

-

Whether or not this key has multiple derivation paths.

-

Get as many keys as derivation paths in this key.

-

For raw keys and single-path extended keys it will return the key itself. -For multipath extended keys it will return a single-path extended key per derivation -path.

-

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 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
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/keys/enum.ExtendedKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ExtendedKey.html deleted file mode 100644 index f8a5e6c1b1..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ExtendedKey.html +++ /dev/null @@ -1,22 +0,0 @@ -ExtendedKey in bdk::keys - Rust

Enum bdk::keys::ExtendedKey

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

Enum for extended keys that can be either xprv or xpub

-

An instance of ExtendedKey can be constructed from an Xpriv -or an Xpub by using the From trait.

-

Defaults to the Legacy context.

-

Variants§

§

Private((Xpriv, PhantomData<Ctx>))

A private extended key, aka an xprv

-
§

Public((Xpub, 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 Xpriv for the -given [Network], if the key contains the private data

-

Transform the ExtendedKey into an Xpub for the -given [Network]

-

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 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 deleted file mode 100644 index a30e1d13e3..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.KeyError.html +++ /dev/null @@ -1,21 +0,0 @@ -KeyError in bdk::keys - Rust

Enum bdk::keys::KeyError

source ·
pub enum KeyError {
-    InvalidScriptContext,
-    InvalidNetwork,
-    InvalidChecksum,
-    Message(String),
-    Bip32(Error),
-    Miniscript(Error),
-}
Expand description

Errors thrown while working with keys

-

Variants§

§

InvalidScriptContext

The key cannot exist in the given script context

-
§

InvalidNetwork

The key is not valid for the given network

-
§

InvalidChecksum

The key has an invalid checksum

-
§

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.

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/keys/enum.ScriptContextEnum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ScriptContextEnum.html deleted file mode 100644 index a6afaf656c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.ScriptContextEnum.html +++ /dev/null @@ -1,19 +0,0 @@ -ScriptContextEnum in bdk::keys - Rust

Enum bdk::keys::ScriptContextEnum

source ·
pub enum ScriptContextEnum {
-    Legacy,
-    Segwitv0,
-    Tap,
-}
Expand description

Enum representation of the known valid ScriptContexts

-

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 -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/keys/enum.SinglePubKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.SinglePubKey.html deleted file mode 100644 index 85d1ae4418..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.SinglePubKey.html +++ /dev/null @@ -1,16 +0,0 @@ -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.

-

Variants§

§

FullKey(PublicKey)

A bitcoin public key (compressed or uncompressed).

-
§

XOnly(XOnlyPublicKey)

An xonly public 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
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
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 deleted file mode 100644 index a0268b8bf7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.any_network.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index af840a4fc7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.mainnet_network.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index f285bbc0d1..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.merge_networks.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 066676deb7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.test_networks.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 85573ace4b..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/index.html +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index bb1823d1c3..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 224ad0a452..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html +++ /dev/null @@ -1,9 +0,0 @@ -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 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 deleted file mode 100644 index 5fce3b2a06..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.PrivateKeyGenerateOptions.html +++ /dev/null @@ -1,11 +0,0 @@ -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.

-

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/keys/struct.SinglePriv.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePriv.html deleted file mode 100644 index daaaded33e..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePriv.html +++ /dev/null @@ -1,14 +0,0 @@ -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.

-

Fields§

§origin: Option<(Fingerprint, DerivationPath)>

Origin information (fingerprint and derivation path).

-
§key: PrivateKey

The private 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
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/keys/struct.SinglePub.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePub.html deleted file mode 100644 index f66bc8e925..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SinglePub.html +++ /dev/null @@ -1,16 +0,0 @@ -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.

-

Fields§

§origin: Option<(Fingerprint, DerivationPath)>

Origin information (fingerprint and derivation path).

-
§key: SinglePubKey

The public 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
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
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 deleted file mode 100644 index aa2dd84b4f..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SortedMultiVec.html +++ /dev/null @@ -1,51 +0,0 @@ -SortedMultiVec in bdk::keys - Rust

Struct bdk::keys::SortedMultiVec

pub struct SortedMultiVec<Pk, Ctx>where
    Pk: MiniscriptKey,
    Ctx: ScriptContext,
{ - pub k: usize, - pub pks: Vec<Pk, Global>, - /* private fields */ -}
Expand description

Contents of a “sortedmulti” descriptor

-

Fields§

§k: usize

signatures required

-
§pks: Vec<Pk, Global>

public keys inside sorted Multi

-

Implementations§

Create a new instance of SortedMultiVec given a list of keys and the threshold

-

Internally checks all the applicable size limits and pubkey types limitations according to the current Ctx.

-

Parse an expression tree into a SortedMultiVec

-

This will panic if fpk returns an uncompressed key when -converting to a Segwit descriptor. To prevent this panic, ensure -fpk returns an error in this case instead.

-

utility function to sanity a sorted multi vec

-

Create Terminal::Multi containing sorted pubkeys

-

Encode as a Bitcoin script

-

Attempt to produce a satisfying witness for the -witness script represented by the parse tree

-

Attempt to produce a witness template given the assets available

-

Size, in bytes of the script-pubkey. If this Miniscript is used outside -of segwit (e.g. in a bare or P2SH descriptor), this quantity should be -multiplied by 4 to compute the weight.

-

In general, it is not recommended to use this function directly, but -to instead call the corresponding function on a Descriptor, which -will handle the segwit/non-segwit technicalities for you.

-

Maximum number of witness elements used to satisfy the Miniscript -fragment, including the witness script itself. Used to estimate -the weight of the VarInt that specifies this number in a serialized -transaction.

-

This function may panic on malformed Miniscript objects which do -not correspond to semantically sane Scripts. (Such scripts should be -rejected at parse time. Any exceptions are bugs.)

-

Maximum size, in bytes, of a satisfying witness. -In general, it is not recommended to use this function directly, but -to instead call the corresponding function on a Descriptor, which -will handle the segwit/non-segwit technicalities for you.

-

All signatures are assumed to be 73 bytes in size, including the -length prefix (segwit) or push opcode (pre-segwit) and sighash -postfix.

-

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
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
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
Converts this 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

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/keys/trait.DerivableKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html deleted file mode 100644 index 3e2c77f65e..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html +++ /dev/null @@ -1,88 +0,0 @@ -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> { ... } -}
Expand description

Trait for keys that can be derived.

-

When extra metadata are provided, a DerivableKey can be transformed into a -DescriptorKey: the trait IntoDescriptorKey is automatically implemented -for (DerivableKey, DerivationPath) and -(DerivableKey, KeySource, DerivationPath) tuples.

-

For key types that don’t encode any indication about the path to use (like bip39), it’s -generally recommended to implement this trait instead of IntoDescriptorKey. The same -rules regarding script context and valid networks apply.

-

Examples

-

Key types that can be directly converted into an Xpriv or -an Xpub can implement only the required into_extended_key() method.

- -
use bdk::bitcoin;
-use bdk::bitcoin::bip32;
-use bdk::keys::{DerivableKey, ExtendedKey, KeyError, ScriptContext};
-
-struct MyCustomKeyType {
-    key_data: bitcoin::PrivateKey,
-    chain_code: [u8; 32],
-    network: bitcoin::Network,
-}
-
-impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
-    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
-        let xprv = bip32::Xpriv {
-            network: self.network,
-            depth: 0,
-            parent_fingerprint: bip32::Fingerprint::default(),
-            private_key: self.key_data.inner,
-            chain_code: bip32::ChainCode::from(&self.chain_code),
-            child_number: bip32::ChildNumber::Normal { index: 0 },
-        };
-
-        xprv.into_extended_key()
-    }
-}
-

Types that don’t internally encode the [Network] in which they are valid need some extra -steps to override the set of valid networks, otherwise only the network specified in the -Xpriv or Xpub will be considered valid.

- -
use bdk::bitcoin;
-use bdk::bitcoin::bip32;
-use bdk::keys::{
-    any_network, DerivableKey, DescriptorKey, ExtendedKey, KeyError, ScriptContext,
-};
-
-struct MyCustomKeyType {
-    key_data: bitcoin::PrivateKey,
-    chain_code: [u8; 32],
-}
-
-impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
-    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
-        let xprv = bip32::Xpriv {
-            network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
-            depth: 0,
-            parent_fingerprint: bip32::Fingerprint::default(),
-            private_key: self.key_data.inner,
-            chain_code: bip32::ChainCode::from(&self.chain_code),
-            child_number: bip32::ChildNumber::Normal { index: 0 },
-        };
-
-        xprv.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)?;
-
-        // Override the set of valid networks here
-        Ok(descriptor_key.override_valid_networks(any_network()))
-    }
-}
-

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 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 deleted file mode 100644 index 9ee8667fb9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ExtScriptContext.html +++ /dev/null @@ -1,13 +0,0 @@ -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 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 deleted file mode 100644 index 368ffa114b..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableDefaultOptions.html +++ /dev/null @@ -1,11 +0,0 @@ -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 -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 deleted file mode 100644 index 095581dfd6..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableKey.html +++ /dev/null @@ -1,21 +0,0 @@ -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;
-
-    fn generate_with_entropy(
        options: Self::Options,
        entropy: Self::Entropy
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>; - - fn generate(
        options: Self::Options
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } -}
Expand description

Trait for keys that can be generated

-

The same rules about ScriptContext and ValidNetworks from IntoDescriptorKey apply.

-

This trait is particularly useful when combined with DerivableKey: if Self -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 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 deleted file mode 100644 index 28530f824b..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.IntoDescriptorKey.html +++ /dev/null @@ -1,106 +0,0 @@ -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 -formats, like the mnemonics used by Electrum wallets, encode internally whether the wallet is -legacy or segwit. Thus, trying to turn a valid legacy mnemonic into a DescriptorKey -that would become part of a segwit descriptor should fail.

-

For key types that do care about this, the ExtScriptContext trait provides some useful -methods that can be used to check at runtime which Ctx is being used.

-

For key types that can do this check statically (because they can only work within a -single Ctx), the “specialized” trait can be implemented to make the compiler handle the type -checking.

-

Keys also have control over the networks they support: constructing the return object with -DescriptorKey::from_public or DescriptorKey::from_secret allows to specify a set of -ValidNetworks.

-

Examples

-

Key type valid in any context:

- -
use bdk::bitcoin::PublicKey;
-
-use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError, ScriptContext};
-
-pub struct MyKeyType {
-    pubkey: PublicKey,
-}
-
-impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for MyKeyType {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        self.pubkey.into_descriptor_key()
-    }
-}
-

Key type that is only valid on mainnet:

- -
use bdk::bitcoin::PublicKey;
-
-use bdk::keys::{
-    mainnet_network, DescriptorKey, DescriptorPublicKey, IntoDescriptorKey, KeyError,
-    ScriptContext, SinglePub, SinglePubKey,
-};
-
-pub struct MyKeyType {
-    pubkey: PublicKey,
-}
-
-impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for MyKeyType {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        Ok(DescriptorKey::from_public(
-            DescriptorPublicKey::Single(SinglePub {
-                origin: None,
-                key: SinglePubKey::FullKey(self.pubkey),
-            }),
-            mainnet_network(),
-        ))
-    }
-}
-

Key type that internally encodes in which context it’s valid. The context is checked at runtime:

- -
use bdk::bitcoin::PublicKey;
-
-use bdk::keys::{DescriptorKey, ExtScriptContext, IntoDescriptorKey, KeyError, ScriptContext};
-
-pub struct MyKeyType {
-    is_legacy: bool,
-    pubkey: PublicKey,
-}
-
-impl<Ctx: ScriptContext + 'static> IntoDescriptorKey<Ctx> for MyKeyType {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        if Ctx::is_legacy() == self.is_legacy {
-            self.pubkey.into_descriptor_key()
-        } else {
-            Err(KeyError::InvalidScriptContext)
-        }
-    }
-}
-

Key type that can only work within miniscript::Segwitv0 context. Only the specialized version -of the trait is implemented.

-

This example deliberately fails to compile, to demonstrate how the compiler can catch when keys -are misused. In this case, the “segwit-only” key is used to build a pkh() descriptor, which -makes the compiler (correctly) fail.

- -
ⓘ
use bdk::bitcoin::PublicKey;
-use core::str::FromStr;
-
-use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError};
-
-pub struct MySegwitOnlyKeyType {
-    pubkey: PublicKey,
-}
-
-impl IntoDescriptorKey<bdk::miniscript::Segwitv0> for MySegwitOnlyKeyType {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<bdk::miniscript::Segwitv0>, KeyError> {
-        self.pubkey.into_descriptor_key()
-    }
-}
-
-let key = MySegwitOnlyKeyType {
-    pubkey: PublicKey::from_str("...")?,
-};
-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 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 deleted file mode 100644 index f9a7d8c18c..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ScriptContext.html +++ /dev/null @@ -1,93 +0,0 @@ -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 16 methods fn check_terminal_non_malleable<Pk>(
        _frag: &Terminal<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
; - fn check_pk<Pk>(pk: &Pk) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
; - fn max_satisfaction_size<Pk>(ms: &Miniscript<Pk, Self>) -> Option<usize>
    where
        Pk: MiniscriptKey
; - fn sig_type() -> SigType; - fn pk_len<Pk>(pk: &Pk) -> usize
    where
        Pk: MiniscriptKey
; - fn name_str() -> &'static str; - - fn check_witness<Pk>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_global_consensus_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_global_policy_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_local_consensus_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_local_policy_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_global_validity<Pk>(
        ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn check_local_validity<Pk>(
        ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, - { ... } - fn top_level_type_check<Pk>(ms: &Miniscript<Pk, Self>) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, - { ... } - fn other_top_level_checks<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, - { ... } - fn top_level_checks<Pk>(ms: &Miniscript<Pk, Self>) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, - { ... } -
}
Expand description

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

-

Required Associated Types§

The consensus key associated with the type. Must be a parseable key

-

Required Methods§

Depending on ScriptContext, fragments can be malleable. For Example, -under Legacy context, PkH is malleable because it is possible to -estimate the cost of satisfaction because of compressed keys -This is currently only used in compiler code for removing malleable -compilations. -This does NOT recursively check if the children of the fragment are -valid or not. Since the compilation proceeds in a leaf to root fashion, -a recursive check is unnecessary.

-

Each context has slightly different rules on what Pks are allowed in descriptors -Legacy/Bare does not allow x_only keys -Segwit does not allow uncompressed keys and x_only keys -Tapscript does not allow uncompressed keys

-

Depending on script context, the size of a satifaction witness may slightly differ.

-

The type of signature required for satisfaction

-

Get the len of public key when serialized based on context -Note that this includes the serialization prefix. Returns -34/66 for Bare/Legacy based on key compressedness -34 for Segwitv0, 33 for Tap

-

Local helper function to display error messages with context

-

Provided Methods§

Check whether the given satisfaction is valid under the ScriptContext -For example, segwit satisfactions may fail if the witness len is more -3600 or number of stack elements are more than 100.

-

Depending on script Context, some of the Terminals might not -be valid under the current consensus rules. -Or some of the script resource limits may have been exceeded. -These miniscripts would never be accepted by the Bitcoin network and hence -it is safe to discard them -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -uncompressed public keys are non-standard and thus invalid. -In LegacyP2SH context, scripts above 520 bytes are invalid. -Post Tapscript upgrade, this would have to consider other nodes. -This does NOT recursively check the miniscript fragments.

-

Depending on script Context, some of the script resource limits -may have been exceeded under the current bitcoin core policy rules -These miniscripts would never be accepted by the Bitcoin network and hence -it is safe to discard them. (unless explicitly disabled by non-standard flag) -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -scripts over 3600 bytes are invalid. -Post Tapscript upgrade, this would have to consider other nodes. -This does NOT recursively check the miniscript fragments.

-

Consensus rules at the Miniscript satisfaction time. -It is possible that some paths of miniscript may exceed resource limits -and our current satisfier and lifting analysis would not work correctly. -For example, satisfaction path(Legacy/Segwitv0) may require more than 201 opcodes.

-

Policy rules at the Miniscript satisfaction time. -It is possible that some paths of miniscript may exceed resource limits -and our current satisfier and lifting analysis would not work correctly. -For example, satisfaction path in Legacy context scriptSig more -than 1650 bytes

-

Check the consensus + policy(if not disabled) rules that are not based -satisfaction

-

Check the consensus + policy(if not disabled) rules including the -ones for satisfaction

-

Check whether the top-level is type B

-

Other top level checks that are context specific

-

Check top level consensus rules.

-

Implementors§

\ No newline at end of file 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 deleted file mode 100644 index 3d60bba0c2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.KeyMap.html +++ /dev/null @@ -1,7 +0,0 @@ -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 -public key from the descriptor.

-
\ No newline at end of file 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 deleted file mode 100644 index 6b5f363426..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.ValidNetworks.html +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 976e018bd9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.descriptor!.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to macro.descriptor.html...

- - - \ 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 deleted file mode 100644 index 3eb46b9520..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html +++ /dev/null @@ -1,80 +0,0 @@ -descriptor in bdk - Rust

Macro bdk::descriptor

source ·
macro_rules! descriptor {
-    ( bare ( $( $minisc:tt )* ) ) => { ... };
-    ( sh ( wsh ( $( $minisc:tt )* ) ) ) => { ... };
-    ( shwsh ( $( $minisc:tt )* ) ) => { ... };
-    ( pk ( $key:expr ) ) => { ... };
-    ( pkh ( $key:expr ) ) => { ... };
-    ( wpkh ( $key:expr ) ) => { ... };
-    ( sh ( wpkh ( $key:expr ) ) ) => { ... };
-    ( shwpkh ( $key:expr ) ) => { ... };
-    ( sh ( $( $minisc:tt )* ) ) => { ... };
-    ( wsh ( $( $minisc:tt )* ) ) => { ... };
-    ( tr ( $internal_key:expr ) ) => { ... };
-    ( tr ( $internal_key:expr, $( $taptree:tt )* ) ) => { ... };
-}
-
Expand description

Macro to write full descriptors with code

-

This macro expands to a Result of -DescriptorTemplateOut and DescriptorError

-

The syntax is very similar to the normal descriptor syntax, with the exception that modifiers -cannot be grouped together. For instance, a descriptor fragment like sdv:older(144) has to be -broken up to s:d:v:older(144).

-

The pk(), pk_k() and pk_h() operands can take as argument any type that implements -IntoDescriptorKey. This means that keys can also be written inline as strings, but in that -case they must be wrapped in quotes, which is another difference compared to the standard -descriptor syntax.

-

Example

-

Signature plus timelock descriptor:

- -
let (my_descriptor, my_keys_map, networks) = bdk::descriptor!(sh(wsh(and_v(v:pk("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"),older(50)))))?;
-
-

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.

-

They both produce the descriptor: wsh(thresh(2,pk(...),s:pk(...),sndv:older(...)))

- -
let my_key_1 = bitcoin::PublicKey::from_str(
-    "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
-)?;
-let my_key_2 =
-    bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
-let my_timelock = 50;
-
-let (descriptor_a, key_map_a, networks) = bdk::descriptor! {
-    wsh (
-        thresh(2, pk(my_key_1), s:pk(my_key_2), s:n:d:v:older(my_timelock))
-    )
-}?;
-
-#[rustfmt::skip]
-let b_items = vec![
-    bdk::fragment!(pk(my_key_1))?,
-    bdk::fragment!(s:pk(my_key_2))?,
-    bdk::fragment!(s:n:d:v:older(my_timelock))?,
-];
-let (descriptor_b, mut key_map_b, networks) = bdk::descriptor!(wsh(thresh_vec(2, b_items)))?;
-
-assert_eq!(descriptor_a, descriptor_b);
-assert_eq!(key_map_a.len(), key_map_b.len());
-
-

Simple 2-of-2 multi-signature, equivalent to: wsh(multi(2, ...))

- -
let my_key_1 = bitcoin::PublicKey::from_str(
-    "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
-)?;
-let my_key_2 =
-    bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
-
-let (descriptor, key_map, networks) = bdk::descriptor! {
-    wsh (
-        multi(2, my_key_1, my_key_2)
-    )
-}?;
-
-

Native-Segwit single-sig, equivalent to: wpkh(...)

- -
let my_key =
-    bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
-
-let (descriptor, key_map, networks) = bdk::descriptor!(wpkh(my_key))?;
-
\ No newline at end of file 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 deleted file mode 100644 index 6eeebba321..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.fragment!.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to macro.fragment.html...

- - - \ No newline at end of file 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 deleted file mode 100644 index c6d9c6c363..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html +++ /dev/null @@ -1,36 +0,0 @@ -fragment in bdk - Rust

Macro bdk::fragment

source ·
macro_rules! fragment {
-    ( $modif:tt : $( $tail:tt )* ) => { ... };
-    ( true ) => { ... };
-    ( false ) => { ... };
-    ( pk_k ( $key:expr ) ) => { ... };
-    ( pk ( $key:expr ) ) => { ... };
-    ( pk_h ( $key:expr ) ) => { ... };
-    ( after ( $value:expr ) ) => { ... };
-    ( older ( $value:expr ) ) => { ... };
-    ( sha256 ( $hash:expr ) ) => { ... };
-    ( hash256 ( $hash:expr ) ) => { ... };
-    ( ripemd160 ( $hash:expr ) ) => { ... };
-    ( hash160 ( $hash:expr ) ) => { ... };
-    ( and_v ( $( $inner:tt )* ) ) => { ... };
-    ( and_b ( $( $inner:tt )* ) ) => { ... };
-    ( and_or ( $( $inner:tt )* ) ) => { ... };
-    ( andor ( $( $inner:tt )* ) ) => { ... };
-    ( or_b ( $( $inner:tt )* ) ) => { ... };
-    ( or_d ( $( $inner:tt )* ) ) => { ... };
-    ( or_c ( $( $inner:tt )* ) ) => { ... };
-    ( or_i ( $( $inner:tt )* ) ) => { ... };
-    ( thresh_vec ( $thresh:expr, $items:expr ) ) => { ... };
-    ( thresh ( $thresh:expr, $( $inner:tt )* ) ) => { ... };
-    ( multi_vec ( $thresh:expr, $keys:expr ) ) => { ... };
-    ( multi ( $thresh:expr $(, $key:expr )+ ) ) => { ... };
-    ( multi_a_vec ( $thresh:expr, $keys:expr ) ) => { ... };
-    ( multi_a ( $thresh:expr $(, $key:expr )+ ) ) => { ... };
-    ( sortedmulti ( $( $inner:tt )* ) ) => { ... };
-    ( sortedmulti_vec ( $( $inner:tt )* ) ) => { ... };
-}
-
Expand description

Macro to write descriptor fragments with code

-

This macro will be expanded to an object of type Result<(Miniscript<DescriptorPublicKey, _>, KeyMap, ValidNetworks), DescriptorError>. It allows writing -fragments of larger descriptors that can be pieced together using fragment!(thresh_vec(m, ...)).

-

The syntax to write macro fragment is the same as documented for the descriptor macro.

-
\ No newline at end of file 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 deleted file mode 100644 index 9b10019bd3..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/index.html +++ /dev/null @@ -1,3 +0,0 @@ -bdk::psbt - Rust

Module bdk::psbt

source ·
Expand description

Additional functions on the rust-bitcoin Psbt 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/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/sidebar-items.js deleted file mode 100644 index 3b7a144401..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"trait":[["PsbtUtils","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 deleted file mode 100644 index 2055aba374..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/psbt/trait.PsbtUtils.html +++ /dev/null @@ -1,14 +0,0 @@ -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. -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 -Psbt 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 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 deleted file mode 100644 index c3780c6996..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["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` `Psbt` structure."],["wallet","Wallet"]],"struct":[["LocalOutput","An unspent output owned by a `Wallet`."],["WeightedUtxo","A [`Utxo`] with its `satisfaction_weight`."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalOutput.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalOutput.html deleted file mode 100644 index 550ed5ec56..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalOutput.html +++ /dev/null @@ -1,22 +0,0 @@ -LocalOutput in bdk - Rust

Struct bdk::LocalOutput

source ·
pub struct LocalOutput {
-    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

-
§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.

-

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/struct.WeightedUtxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html deleted file mode 100644 index ebdd0ce84e..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html +++ /dev/null @@ -1,15 +0,0 @@ -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 -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/types/enum.KeychainKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/enum.KeychainKind.html deleted file mode 100644 index 03524a9b17..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/enum.KeychainKind.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to ../../bdk/enum.KeychainKind.html...

- - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/enum.Utxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/enum.Utxo.html deleted file mode 100644 index 03f5add737..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/enum.Utxo.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to ../../bdk/enum.Utxo.html...

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

Redirecting to ../../bdk/struct.LocalOutput.html...

- - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.WeightedUtxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.WeightedUtxo.html deleted file mode 100644 index 5e7d643399..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.WeightedUtxo.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to ../../bdk/struct.WeightedUtxo.html...

- - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/enum.Error.html deleted file mode 100644 index 6119594507..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/enum.Error.html +++ /dev/null @@ -1,22 +0,0 @@ -Error in bdk::wallet::coin_selection - Rust
pub enum Error {
-    InsufficientFunds {
-        needed: u64,
-        available: u64,
-    },
-    BnBNoExactMatch,
-    BnBTotalTriesExceeded,
-}
Expand description

Errors that can be thrown by the coin_selection module

-

Variants§

§

InsufficientFunds

Fields

§needed: u64

Sats needed for some transaction

-
§available: u64

Sats available for spending

-

Wallet’s UTXO set is not enough to cover recipient’s requested plus fee

-
§

BnBNoExactMatch

Branch and bound coin selection tries to avoid needing a change by finding the right inputs for -the desired outputs plus fee, if there is not such combination this error is thrown

-
§

BnBTotalTriesExceeded

Branch and bound coin selection possible attempts with sufficiently big UTXO set could grow -exponentially, thus a limit is set, and when hit, this error is thrown

-

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/wallet/coin_selection/enum.Excess.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/enum.Excess.html deleted file mode 100644 index 0d6cd4d4f2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/enum.Excess.html +++ /dev/null @@ -1,24 +0,0 @@ -Excess in bdk::wallet::coin_selection - Rust
pub enum Excess {
-    NoChange {
-        dust_threshold: u64,
-        remaining_amount: u64,
-        change_fee: u64,
-    },
-    Change {
-        amount: u64,
-        fee: u64,
-    },
-}
Expand description

Remaining amount after performing coin selection

-

Variants§

§

NoChange

Fields

§dust_threshold: u64

Threshold to consider amount as dust for this particular change script_pubkey

-
§remaining_amount: u64

Exceeding amount of current selection over outgoing value and fee costs

-
§change_fee: u64

The calculated fee for the drain TxOut with the selected script_pubkey

-

It’s not possible to create spendable output from excess using the current drain output

-
§

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.

-

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/wallet/coin_selection/fn.decide_change.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/fn.decide_change.html deleted file mode 100644 index bb373c3b1a..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/fn.decide_change.html +++ /dev/null @@ -1,8 +0,0 @@ -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

-
    -
  • remaining_amount: the amount in which the selected coins exceed the target amount
  • -
  • fee_rate: required fee rate for the current selection
  • -
  • drain_script: script to consider change creation
  • -
-
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html deleted file mode 100644 index 371d32c28d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html +++ /dev/null @@ -1,75 +0,0 @@ -bdk::wallet::coin_selection - Rust

Module bdk::wallet::coin_selection

source ·
Expand description

Coin selection

-

This module provides the trait CoinSelectionAlgorithm that can be implemented to -define custom coin selection algorithms.

-

You can specify a custom coin selection algorithm through the coin_selection method on -TxBuilder. DefaultCoinSelectionAlgorithm aliases the coin selection algorithm that will -be used if it is not explicitly set.

-

Example

-
#[derive(Debug)]
-struct AlwaysSpendEverything;
-
-impl CoinSelectionAlgorithm for AlwaysSpendEverything {
-    fn coin_select(
-        &self,
-        required_utxos: Vec<WeightedUtxo>,
-        optional_utxos: Vec<WeightedUtxo>,
-        fee_rate: FeeRate,
-        target_amount: u64,
-        drain_script: &Script,
-    ) -> Result<CoinSelectionResult, coin_selection::Error> {
-        let mut selected_amount = 0;
-        let mut additional_weight = Weight::ZERO;
-        let all_utxos_selected = required_utxos
-            .into_iter()
-            .chain(optional_utxos)
-            .scan(
-                (&mut selected_amount, &mut additional_weight),
-                |(selected_amount, additional_weight), weighted_utxo| {
-                    **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
-                    **additional_weight += Weight::from_wu(
-                        (TxIn::default().segwit_weight().to_wu()
-                            + weighted_utxo.satisfaction_weight as u64)
-                            as u64,
-                    );
-                    Some(weighted_utxo.utxo)
-                },
-            )
-            .collect::<Vec<_>>();
-        let additional_fees = (fee_rate * additional_weight).to_sat();
-        let amount_needed_with_fees = additional_fees + target_amount;
-        if selected_amount < amount_needed_with_fees {
-            return Err(coin_selection::Error::InsufficientFunds {
-                needed: amount_needed_with_fees,
-                available: selected_amount,
-            });
-        }
-
-        let remaining_amount = selected_amount - amount_needed_with_fees;
-
-        let excess = decide_change(remaining_amount, fee_rate, drain_script);
-
-        Ok(CoinSelectionResult {
-            selected: all_utxos_selected,
-            fee_amount: additional_fees,
-            excess,
-        })
-    }
-}
-
-// create wallet, sync, ...
-
-let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
-    .unwrap()
-    .require_network(Network::Testnet)
-    .unwrap();
-let psbt = {
-    let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
-    builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
-    builder.finish()?
-};
-
-// inspect, sign, broadcast, ...
-
-

Structs

Branch and bound coin selection
Result of a successful coin selection
Simple and dumb coin selection
OldestFirstCoinSelection always picks the utxo with the smallest blockheight to add to the selected coins next

Enums

Errors that can be thrown by the coin_selection module
Remaining amount after performing coin selection

Traits

Trait for generalized coin selection algorithms

Functions

Decide if change can be created

Type Definitions

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/coin_selection/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/sidebar-items.js deleted file mode 100644 index 7ab6c39cfa..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["Error","Errors that can be thrown by the `coin_selection` module"],["Excess","Remaining amount after performing coin selection"]],"fn":[["decide_change","Decide if change can be created"]],"struct":[["BranchAndBoundCoinSelection","Branch and bound coin selection"],["CoinSelectionResult","Result of a successful coin selection"],["LargestFirstCoinSelection","Simple and dumb coin selection"],["OldestFirstCoinSelection","OldestFirstCoinSelection always picks the utxo with the smallest blockheight to add to the selected coins next"]],"trait":[["CoinSelectionAlgorithm","Trait for generalized coin selection algorithms"]],"type":[["DefaultCoinSelectionAlgorithm","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/coin_selection/struct.BranchAndBoundCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html deleted file mode 100644 index c7792b9bb2..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html +++ /dev/null @@ -1,9 +0,0 @@ -BranchAndBoundCoinSelection in bdk::wallet::coin_selection - Rust
pub struct BranchAndBoundCoinSelection { /* private fields */ }
Expand description

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

-

Implementations§

Create new instance with target size for change output

-

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 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.CoinSelectionResult.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.CoinSelectionResult.html deleted file mode 100644 index 6fc1ea28ea..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.CoinSelectionResult.html +++ /dev/null @@ -1,16 +0,0 @@ -CoinSelectionResult in bdk::wallet::coin_selection - Rust
pub struct CoinSelectionResult {
-    pub selected: Vec<Utxo>,
-    pub fee_amount: u64,
-    pub excess: Excess,
-}
Expand description

Result of a successful coin selection

-

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.

-

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/wallet/coin_selection/struct.LargestFirstCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html deleted file mode 100644 index 5cdbfacf1f..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html +++ /dev/null @@ -1,9 +0,0 @@ -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.

-

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/wallet/coin_selection/struct.OldestFirstCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.OldestFirstCoinSelection.html deleted file mode 100644 index 27f08d9b09..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.OldestFirstCoinSelection.html +++ /dev/null @@ -1,9 +0,0 @@ -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.

-

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/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html deleted file mode 100644 index a50b5acc24..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html +++ /dev/null @@ -1,21 +0,0 @@ -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

-
    -
  • database: a reference to the wallet’s database that can be used to lookup additional -details for a specific UTXO
  • -
  • required_utxos: the utxos that must be spent regardless of target_amount with their -weight cost
  • -
  • optional_utxos: the remaining available utxos to satisfy target_amount with their -weight cost
  • -
  • fee_rate: fee rate to use
  • -
  • target_amount: the outgoing amount in satoshis and the fees already -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 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 deleted file mode 100644 index 09a3d3e37f..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html +++ /dev/null @@ -1,4 +0,0 @@ -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.ApplyBlockError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.ApplyBlockError.html deleted file mode 100644 index da3f8f1227..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.ApplyBlockError.html +++ /dev/null @@ -1,18 +0,0 @@ -ApplyBlockError in bdk::wallet - Rust

Enum bdk::wallet::ApplyBlockError

source ·
pub enum ApplyBlockError {
-    CannotConnect(CannotConnectError),
-    UnexpectedConnectedToHash {
-        connected_to_hash: BlockHash,
-        expected_hash: BlockHash,
-    },
-}
Expand description

An error that may occur when applying a block to Wallet.

-

Variants§

§

CannotConnect(CannotConnectError)

Occurs when the update chain cannot connect with original chain.

-
§

UnexpectedConnectedToHash

Fields

§connected_to_hash: BlockHash

Block hash of connected_to.

-
§expected_hash: BlockHash

Expected block hash of connected_to, as derived from block.

-

Occurs when the connected_to hash does not match the hash derived from block.

-

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/enum.InsertTxError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.InsertTxError.html deleted file mode 100644 index 80e46eb4f9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.InsertTxError.html +++ /dev/null @@ -1,17 +0,0 @@ -InsertTxError in bdk::wallet - Rust

Enum bdk::wallet::InsertTxError

source ·
pub enum InsertTxError {
-    ConfirmationHeightCannotBeGreaterThanTip {
-        tip_height: u32,
-        tx_height: u32,
-    },
-}
Expand description

An error that may occur when inserting a transaction into Wallet.

-

Variants§

§

ConfirmationHeightCannotBeGreaterThanTip

Fields

§tip_height: u32

The internal chain’s tip height.

-
§tx_height: u32

The introduced transaction’s confirmation height.

-

The error variant that occurs when the caller attempts to insert a transaction with a -confirmation height that is greater than the internal chain tip.

-

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/enum.LoadError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.LoadError.html deleted file mode 100644 index c60a073166..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.LoadError.html +++ /dev/null @@ -1,22 +0,0 @@ -LoadError in bdk::wallet - Rust

Enum bdk::wallet::LoadError

source ·
pub enum LoadError {
-    Descriptor(DescriptorError),
-    Persist(Error),
-    NotInitialized,
-    MissingNetwork,
-    MissingGenesis,
-    MissingDescriptor,
-}
Expand description

The error type when loading a Wallet from persistence.

-

Method load may return this error.

-

Variants§

§

Descriptor(DescriptorError)

There was a problem with the passed-in descriptor(s).

-
§

Persist(Error)

Loading data from the persistence backend failed.

-
§

NotInitialized

Wallet not initialized, persistence backend is empty.

-
§

MissingNetwork

Data loaded from persistence is missing network type.

-
§

MissingGenesis

Data loaded from persistence is missing genesis hash.

-
§

MissingDescriptor

Data loaded from persistence is missing descriptor.

-

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/enum.NewError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.NewError.html deleted file mode 100644 index 8e5b121c93..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.NewError.html +++ /dev/null @@ -1,16 +0,0 @@ -NewError in bdk::wallet - Rust

Enum bdk::wallet::NewError

source ·
pub enum NewError {
-    NonEmptyDatabase,
-    Descriptor(DescriptorError),
-    Persist(Error),
-}
Expand description

The error type when constructing a fresh Wallet.

-

Methods new and new_with_genesis_hash may return this error.

-

Variants§

§

NonEmptyDatabase

Database already has data.

-
§

Descriptor(DescriptorError)

There was problem with the passed-in descriptor(s).

-
§

Persist(Error)

We were unable to write the wallet’s data to the persistence 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/enum.NewOrLoadError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.NewOrLoadError.html deleted file mode 100644 index 11173e243a..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.NewOrLoadError.html +++ /dev/null @@ -1,37 +0,0 @@ -NewOrLoadError in bdk::wallet - Rust

Enum bdk::wallet::NewOrLoadError

source ·
pub enum NewOrLoadError {
-    Descriptor(DescriptorError),
-    Persist(Error),
-    NotInitialized,
-    LoadedGenesisDoesNotMatch {
-        expected: BlockHash,
-        got: Option<BlockHash>,
-    },
-    LoadedNetworkDoesNotMatch {
-        expected: Network,
-        got: Option<Network>,
-    },
-    LoadedDescriptorDoesNotMatch {
-        got: Option<ExtendedDescriptor>,
-        keychain: KeychainKind,
-    },
-}
Expand description

Error type for when we try load a Wallet from persistence and creating it if non-existent.

-

Methods new_or_load and new_or_load_with_genesis_hash may return this error.

-

Variants§

§

Descriptor(DescriptorError)

There is a problem with the passed-in descriptor.

-
§

Persist(Error)

Either writing to or loading from the persistence backend failed.

-
§

NotInitialized

Wallet is not initialized, persistence backend is empty.

-
§

LoadedGenesisDoesNotMatch

Fields

§expected: BlockHash

The expected genesis block hash.

-
§got: Option<BlockHash>

The block hash loaded from persistence.

-

The loaded genesis hash does not match what was provided.

-
§

LoadedNetworkDoesNotMatch

Fields

§expected: Network

The expected network type.

-
§got: Option<Network>

The network type loaded from persistence.

-

The loaded network type does not match what was provided.

-
§

LoadedDescriptorDoesNotMatch

Fields

§got: Option<ExtendedDescriptor>

The descriptor loaded from persistence.

-
§keychain: KeychainKind

The keychain of the descriptor not matching

-

The loaded desccriptor does not match what was provided.

-

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/error/enum.BuildFeeBumpError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/enum.BuildFeeBumpError.html deleted file mode 100644 index ab9e003fde..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/enum.BuildFeeBumpError.html +++ /dev/null @@ -1,19 +0,0 @@ -BuildFeeBumpError in bdk::wallet::error - Rust
pub enum BuildFeeBumpError {
-    UnknownUtxo(OutPoint),
-    TransactionNotFound(Txid),
-    TransactionConfirmed(Txid),
-    IrreplaceableTransaction(Txid),
-    FeeRateUnavailable,
-}
Expand description

Error returned from Wallet::build_fee_bump

-

Variants§

§

UnknownUtxo(OutPoint)

Happens when trying to spend an UTXO that is not in the internal database

-
§

TransactionNotFound(Txid)

Thrown when a tx is not found in the internal database

-
§

TransactionConfirmed(Txid)

Happens when trying to bump a transaction that is already confirmed

-
§

IrreplaceableTransaction(Txid)

Trying to replace a tx that has a sequence >= 0xFFFFFFFE

-
§

FeeRateUnavailable

Node doesn’t have data to estimate a fee rate

-

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/error/enum.CreateTxError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/enum.CreateTxError.html deleted file mode 100644 index fde86b45a7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/enum.CreateTxError.html +++ /dev/null @@ -1,76 +0,0 @@ -CreateTxError in bdk::wallet::error - Rust

Enum bdk::wallet::error::CreateTxError

source ·
pub enum CreateTxError {
-
Show 22 variants Descriptor(DescriptorError), - Persist(Error), - Policy(PolicyError), - SpendingPolicyRequired(KeychainKind), - Version0, - Version1Csv, - LockTime { - requested: LockTime, - required: LockTime, - }, - RbfSequence, - RbfSequenceCsv { - rbf: Sequence, - csv: Sequence, - }, - FeeTooLow { - required: u64, - }, - FeeRateTooLow { - required: FeeRate, - }, - NoUtxosSelected, - OutputBelowDustLimit(usize), - ChangePolicyDescriptor, - CoinSelection(Error), - InsufficientFunds { - needed: u64, - available: u64, - }, - NoRecipients, - Psbt(Error), - MissingKeyOrigin(String), - UnknownUtxo, - MissingNonWitnessUtxo(OutPoint), - MiniscriptPsbt(MiniscriptPsbtError), -
}
Expand description

Error returned from TxBuilder::finish

-

Variants§

§

Descriptor(DescriptorError)

There was a problem with the descriptors passed in

-
§

Persist(Error)

We were unable to load wallet data from or write wallet data to the persistence backend

-
§

Policy(PolicyError)

There was a problem while extracting and manipulating policies

-
§

SpendingPolicyRequired(KeychainKind)

Spending policy is not compatible with this KeychainKind

-
§

Version0

Requested invalid transaction version ‘0’

-
§

Version1Csv

Requested transaction version 1, but at least 2 is needed to use OP_CSV

-
§

LockTime

Fields

§requested: LockTime

Requested LockTime

-
§required: LockTime

Required LockTime

-

Requested LockTime is less than is required to spend from this script

-
§

RbfSequence

Cannot enable RBF with a Sequence >= 0xFFFFFFFE

-
§

RbfSequenceCsv

Fields

§rbf: Sequence

Given RBF Sequence

-
§csv: Sequence

Required OP_CSV Sequence

-

Cannot enable RBF with Sequence given a required OP_CSV

-
§

FeeTooLow

Fields

§required: u64

Required fee absolute value (satoshi)

-

When bumping a tx the absolute fee requested is lower than replaced tx absolute fee

-
§

FeeRateTooLow

Fields

§required: FeeRate

Required fee rate

-

When bumping a tx the fee rate requested is lower than required

-
§

NoUtxosSelected

manually_selected_only option is selected but no utxo has been passed

-
§

OutputBelowDustLimit(usize)

Output created is under the dust limit, 546 satoshis

-
§

ChangePolicyDescriptor

The change_policy was set but the wallet does not have a change_descriptor

-
§

CoinSelection(Error)

There was an error with coin selection

-
§

InsufficientFunds

Fields

§needed: u64

Sats needed for some transaction

-
§available: u64

Sats available for spending

-

Wallet’s UTXO set is not enough to cover recipient’s requested plus fee

-
§

NoRecipients

Cannot build a tx without recipients

-
§

Psbt(Error)

Partially signed bitcoin transaction error

-
§

MissingKeyOrigin(String)

In order to use the TxBuilder::add_global_xpubs option every extended -key in the descriptor must either be a master key itself (having depth = 0) or have an -explicit origin provided

-
§

UnknownUtxo

Happens when trying to spend an UTXO that is not in the internal database

-
§

MissingNonWitnessUtxo(OutPoint)

Missing non_witness_utxo on foreign utxo for given OutPoint

-
§

MiniscriptPsbt(MiniscriptPsbtError)

Miniscript PSBT 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.

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/error/enum.MiniscriptPsbtError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/enum.MiniscriptPsbtError.html deleted file mode 100644 index 6b674e1649..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/enum.MiniscriptPsbtError.html +++ /dev/null @@ -1,15 +0,0 @@ -MiniscriptPsbtError in bdk::wallet::error - Rust
pub enum MiniscriptPsbtError {
-    Conversion(ConversionError),
-    UtxoUpdate(UtxoUpdateError),
-    OutputUpdate(OutputUpdateError),
-}
Expand description

Errors returned by miniscript when updating inconsistent PSBTs

-

Variants§

§

Conversion(ConversionError)

Descriptor key conversion error

-
§

UtxoUpdate(UtxoUpdateError)

Return error type for PsbtExt::update_input_with_descriptor

-
§

OutputUpdate(OutputUpdateError)

Return error type for PsbtExt::update_output_with_descriptor

-

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.

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/wallet/error/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/index.html deleted file mode 100644 index b07f136447..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/index.html +++ /dev/null @@ -1,3 +0,0 @@ -bdk::wallet::error - Rust

Module bdk::wallet::error

source ·
Expand description

Errors that can be thrown by the Wallet

-

Enums

Error returned from TxBuilder::finish
Errors returned by miniscript when updating inconsistent PSBTs
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/sidebar-items.js deleted file mode 100644 index 4f379f6341..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/error/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["BuildFeeBumpError","Error returned from `Wallet::build_fee_bump`"],["CreateTxError","Error returned from `TxBuilder::finish`"],["MiniscriptPsbtError","Errors returned by miniscript when updating inconsistent PSBTs"]]}; \ 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 deleted file mode 100644 index c7024ef4fd..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html +++ /dev/null @@ -1,26 +0,0 @@ -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#"{
-    "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
-    "blockheight":1782088,
-    "label":"testnet"
-}"#;
-
-let import = FullyNodedExport::from_str(import)?;
-let wallet = Wallet::new_no_persist(
-    &import.descriptor(),
-    import.change_descriptor().as_ref(),
-    Network::Testnet,
-)?;
-

Export a Wallet

-
let wallet = Wallet::new_no_persist(
-    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
-    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
-    Network::Testnet,
-)?;
-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/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/sidebar-items.js deleted file mode 100644 index 07ee950354..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"struct":[["FullyNodedExport","Structure that contains the export of a wallet"]],"type":[["WalletExport","Alias for [`FullyNodedExport`]"]]}; \ 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 deleted file mode 100644 index 67c0c63a4e..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.FullyNodedExport.html +++ /dev/null @@ -1,24 +0,0 @@ -FullyNodedExport in bdk::wallet::export - Rust
pub struct FullyNodedExport {
-    pub blockheight: u32,
-    pub label: String,
-    /* private fields */
-}
Expand description

Structure that contains the export of a wallet

-

For a usage example see this module’s documentation.

-

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

-

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.

-

If include_blockheight is true, this function will look into the wallet’s database -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
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
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.

-
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/type.WalletExport.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/type.WalletExport.html deleted file mode 100644 index 6874264e03..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/type.WalletExport.html +++ /dev/null @@ -1,3 +0,0 @@ -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.wallet_name_from_descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.wallet_name_from_descriptor.html deleted file mode 100644 index 7a531e48c7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.wallet_name_from_descriptor.html +++ /dev/null @@ -1,4 +0,0 @@ -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, DescriptorError>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/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/index.html deleted file mode 100644 index bc15ec6dcd..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/index.html +++ /dev/null @@ -1,7 +0,0 @@ -bdk::wallet - Rust

Module bdk::wallet

source ·
Expand description

Wallet

-

This module defines the Wallet.

-

Modules

Coin selection
Errors that can be thrown by the Wallet
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 into various categories.
The changes made to a wallet by applying an Update.
An update to Wallet.
A Bitcoin wallet

Enums

An error that may occur when applying a block to Wallet.
An error that may occur when inserting a transaction into Wallet.
The error type when loading a Wallet from persistence.
The error type when constructing a fresh Wallet.
Error type for when we try load a Wallet from persistence and creating it if non-existent.

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

Deterministically generate a unique name given the descriptors defining the wallet
\ 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 deleted file mode 100644 index b5896f9a0d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["ApplyBlockError","An error that may occur when applying a block to [`Wallet`]."],["InsertTxError","An error that may occur when inserting a transaction into [`Wallet`]."],["LoadError","The error type when loading a [`Wallet`] from persistence."],["NewError","The error type when constructing a fresh [`Wallet`]."],["NewOrLoadError","Error type for when we try load a [`Wallet`] from persistence and creating it if non-existent."]],"fn":[["wallet_name_from_descriptor","Deterministically generate a unique name given the descriptors defining the wallet"]],"mod":[["coin_selection","Coin selection"],["error","Errors that can be thrown by the `Wallet`"],["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 into various categories."],["ChangeSet","The changes made to a wallet by applying an [`Update`]."],["Update","An update to [`Wallet`]."],["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 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 deleted file mode 100644 index d2150ec9e8..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerContext.html +++ /dev/null @@ -1,20 +0,0 @@ -SignerContext in bdk::wallet::signer - Rust
pub enum SignerContext {
-    Legacy,
-    Segwitv0,
-    Tap {
-        is_internal_key: bool,
-    },
-}
Expand description

Signing context

-

Used by our software signers to determine the type of signatures to make

-

Variants§

§

Legacy

Legacy context

-
§

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 -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/wallet/signer/enum.SignerError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html deleted file mode 100644 index c4a513b715..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html +++ /dev/null @@ -1,42 +0,0 @@ -SignerError in bdk::wallet::signer - Rust

Enum bdk::wallet::signer::SignerError

source ·
pub enum SignerError {
-
Show 14 variants MissingKey, - InvalidKey, - UserCanceled, - InputIndexOutOfRange, - MissingNonWitnessUtxo, - InvalidNonWitnessUtxo, - MissingWitnessUtxo, - MissingWitnessScript, - MissingHdKeypath, - NonStandardSighash, - InvalidSighash, - SighashError(Error), - MiniscriptPsbt(MiniscriptPsbtError), - External(String), -
}
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

-
§

InputIndexOutOfRange

Input index is out of range

-
§

MissingNonWitnessUtxo

The non_witness_utxo field of the transaction is required to sign this input

-
§

InvalidNonWitnessUtxo

The non_witness_utxo specified is invalid

-
§

MissingWitnessUtxo

The witness_utxo field of the transaction is required to sign this input

-
§

MissingWitnessScript

The witness_script field of the transaction is required to sign this input

-
§

MissingHdKeypath

The fingerprint and derivation path are missing from the psbt input

-
§

NonStandardSighash

The psbt contains a non-SIGHASH_ALL sighash in one of its input and the user hasn’t -explicitly allowed them

-

To enable signing transactions with non-standard sighashes set -SignOptions::allow_all_sighashes to true.

-
§

InvalidSighash

Invalid SIGHASH for the signing context in use

-
§

SighashError(Error)

Error while computing the hash to sign

-
§

MiniscriptPsbt(MiniscriptPsbtError)

Miniscript PSBT error

-
§

External(String)

To be used only by external libraries implementing InputSigner or -TransactionSigner, so that they can return their own custom errors, without having to -modify SignerError in BDK.

-

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/wallet/signer/enum.SignerId.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html deleted file mode 100644 index 5acb4010a0..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html +++ /dev/null @@ -1,19 +0,0 @@ -SignerId in bdk::wallet::signer - Rust

Enum bdk::wallet::signer::SignerId

source ·
pub enum SignerId {
-    PkHash(Hash),
-    Fingerprint(Fingerprint),
-    Dummy(u64),
-}
Expand description

Identifier of a signer in the SignersContainers. Used as a key to find the right signer among -multiple of them

-

Variants§

§

PkHash(Hash)

Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA public key

-
§

Fingerprint(Fingerprint)

The fingerprint of a BIP32 extended key

-
§

Dummy(u64)

Dummy identifier

-

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.
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

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/wallet/signer/enum.TapLeavesOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.TapLeavesOptions.html deleted file mode 100644 index 0b90a48238..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.TapLeavesOptions.html +++ /dev/null @@ -1,19 +0,0 @@ -TapLeavesOptions in bdk::wallet::signer - Rust
pub enum TapLeavesOptions {
-    All,
-    Include(Vec<TapLeafHash>),
-    Exclude(Vec<TapLeafHash>),
-    None,
-}
Expand description

Customize which taproot script-path leaves the signer should sign.

-

Variants§

§

All

The signer will sign all the leaves it has a key for.

-
§

Include(Vec<TapLeafHash>)

The signer won’t sign leaves other than the ones specified. Note that it could still ignore -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 -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/wallet/signer/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html deleted file mode 100644 index 27f5f3e406..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html +++ /dev/null @@ -1,48 +0,0 @@ -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.

- -
#[derive(Debug)]
-struct CustomSigner {
-    device: CustomHSM,
-}
-
-impl CustomSigner {
-    fn connect() -> Self {
-        CustomSigner { device: CustomHSM::connect() }
-    }
-}
-
-impl SignerCommon for CustomSigner {
-    fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
-        self.device.get_id()
-    }
-}
-
-impl InputSigner for CustomSigner {
-    fn sign_input(
-        &self,
-        psbt: &mut Psbt,
-        input_index: usize,
-        _sign_options: &SignOptions,
-        _secp: &Secp256k1<All>,
-    ) -> Result<(), SignerError> {
-        self.device.hsm_sign_input(psbt, input_index)?;
-
-        Ok(())
-    }
-}
-
-let custom_signer = CustomSigner::connect();
-
-let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-let mut wallet = Wallet::new_no_persist(descriptor, None, Network::Testnet)?;
-wallet.add_signer(
-    KeychainKind::External,
-    SignerOrdering(200),
-    Arc::new(custom_signer)
-);
-
-

Structs

Options for a software signer
Defines the order in which signers are called
Wrapper to pair a signer with its context
Container for multiple signers

Enums

Signing context
Signing error
Identifier of a signer in the SignersContainers. Used as a key to find the right signer among -multiple of them
Customize which taproot script-path leaves the signer should sign.

Traits

PSBT Input signer
Common signer methods
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/sidebar-items.js deleted file mode 100644 index 34ced712cb..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["SignerContext","Signing context"],["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"],["TapLeavesOptions","Customize which taproot script-path leaves the signer should sign."]],"struct":[["SignOptions","Options for a software signer"],["SignerOrdering","Defines the order in which signers are called"],["SignerWrapper","Wrapper to pair a signer with its context"],["SignersContainer","Container for multiple signers"]],"trait":[["InputSigner","PSBT Input signer"],["SignerCommon","Common signer methods"],["TransactionSigner","PSBT signer"]]}; \ No newline at end of file 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 deleted file mode 100644 index b9085644ba..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignOptions.html +++ /dev/null @@ -1,53 +0,0 @@ -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,
-    pub remove_partial_sigs: bool,
-    pub remove_taproot_extras: bool,
-    pub try_finalize: bool,
-    pub tap_leaves_options: TapLeavesOptions,
-    pub sign_with_tap_internal_key: bool,
-    pub allow_grinding: bool,
-}
Expand description

Options for a software signer

-

Adjust the behavior of our software signers and the way a transaction is finalized

-

Fields§

§trust_witness_utxo: bool

Whether the signer should trust the witness_utxo, if the non_witness_utxo hasn’t been -provided

-

Defaults to false to mitigate the “SegWit bug” which should trick the wallet into -paying a fee larger than expected.

-

Some wallets, especially if relatively old, might not provide the non_witness_utxo for -SegWit transactions in the PSBT they generate: in those cases setting this to true -should correctly produce a signature, at the expense of an increased trust in the creator -of the PSBT.

-

For more details see: https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd

-
§assume_height: Option<u32>

Whether the wallet should assume a specific height has been reached when trying to finalize -a transaction

-

The wallet will only “use” a timelock to satisfy the spending policy of an input if the -timelock height has already been reached. This option allows overriding the “current height” to let the -wallet use timelocks in the future to spend a coin.

-
§allow_all_sighashes: bool

Whether the signer should use the sighash_type set in the PSBT when signing, no matter -what its value is

-

Defaults to false which will only allow signing using SIGHASH_ALL.

-
§remove_partial_sigs: bool

Whether to remove partial signatures from the PSBT inputs while finalizing PSBT.

-

Defaults to true which will remove partial signatures during finalization.

-
§remove_taproot_extras: bool

Whether to remove taproot specific fields from the PSBT on finalization.

-

For inputs this includes the taproot internal key, merkle root, and individual -scripts and signatures. For both inputs and outputs it includes key origin info.

-

Defaults to true which will remove all of the above mentioned fields when finalizing.

-

See BIP371 for details.

-
§try_finalize: bool

Whether to try finalizing the PSBT after the inputs are signed.

-

Defaults to true which will try finalizing PSBT after inputs are signed.

-
§tap_leaves_options: TapLeavesOptions

Specifies which Taproot script-spend leaves we should sign for. This option is -ignored if we’re signing a non-taproot PSBT.

-

Defaults to All, i.e., the wallet will sign all the leaves it has a key for.

-
§sign_with_tap_internal_key: bool

Whether we should try to sign a taproot transaction with the taproot internal key -or not. This option is ignored if we’re signing a non-taproot PSBT.

-

Defaults to true, i.e., we always try to sign with the taproot internal key.

-
§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.

-

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/wallet/signer/struct.SignerOrdering.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html deleted file mode 100644 index 9ee2a00bc3..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html +++ /dev/null @@ -1,14 +0,0 @@ -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 -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
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 deleted file mode 100644 index 2690479b9b..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerWrapper.html +++ /dev/null @@ -1,8 +0,0 @@ -SignerWrapper in bdk::wallet::signer - Rust

Struct bdk::wallet::signer::SignerWrapper

source ·
pub struct SignerWrapper<S: Sized + Debug + Clone> { /* private fields */ }
Expand description

Wrapper 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
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
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 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 deleted file mode 100644 index 1fcb2c38ea..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html +++ /dev/null @@ -1,18 +0,0 @@ -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 -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.

-

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/wallet/signer/trait.InputSigner.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.InputSigner.html deleted file mode 100644 index acb414a497..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.InputSigner.html +++ /dev/null @@ -1,9 +0,0 @@ -InputSigner in bdk::wallet::signer - Rust

Trait bdk::wallet::signer::InputSigner

source ·
pub trait InputSigner: SignerCommon {
-    fn sign_input(
        &self,
        psbt: &mut Psbt,
        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 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 deleted file mode 100644 index fb369645f4..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.SignerCommon.html +++ /dev/null @@ -1,14 +0,0 @@ -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

-

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

-

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 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 deleted file mode 100644 index 399a7be3ea..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.TransactionSigner.html +++ /dev/null @@ -1,8 +0,0 @@ -TransactionSigner in bdk::wallet::signer - Rust
pub trait TransactionSigner: SignerCommon {
-    fn sign_transaction(
        &self,
        psbt: &mut Psbt,
        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§

\ 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 deleted file mode 100644 index 960e77bb9a..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.AddressInfo.html +++ /dev/null @@ -1,77 +0,0 @@ -AddressInfo in bdk::wallet - Rust

Struct bdk::wallet::AddressInfo

source ·
pub struct AddressInfo {
-    pub index: u32,
-    pub address: Address,
-    pub keychain: KeychainKind,
-}
Expand description

A derived address and the index it was found at. -For convenience this automatically derefs to Address

-

Fields§

§index: u32

Child index of this address

-
§address: Address

Address

-
§keychain: KeychainKind

Type of keychain

-

Methods from Deref<Target = Address>§

Returns a reference to the payload of this address.

-

Returns a reference to the network of this address.

-

Returns a reference to the unchecked address, which is dangerous to use if the address -is invalid in the context of NetworkUnchecked.

-

Gets the address type of the address.

-
Returns
-

None if unknown, non-standard or related to the future witness version.

-

Checks whether or not the address is following Bitcoin standardness rules when -spending from this address. NOT to be called by senders.

-
-Spending Standardness -

For forward compatibility, the senders must send to any [Address]. Receivers -can use this method to check whether or not they can spend from this address.

-

SegWit addresses with unassigned witness versions or non-standard program sizes are -considered non-standard.

-
-

Generates a script pubkey spending to this address.

-

Creates a URI string bitcoin:address optimized to be encoded in QR codes.

-

If the address is bech32, the address becomes uppercase. -If the address is base58, the address is left mixed case.

-

Quoting BIP 173 “inside QR codes uppercase SHOULD be used, as those permit the use of -alphanumeric mode, which is 45% more compact than the normal byte mode.”

-

Note however that despite BIP21 explicitly stating that the bitcoin: prefix should be -parsed as case-insensitive many wallets got this wrong and don’t parse correctly. -See compatibility table.

-

If you want to avoid allocation you can use alternate display instead:

- -

-write!(writer, "{:#}", address)?;
-
-

Returns true if the given pubkey is directly related to the address payload.

-

This is determined by directly comparing the address payload with either the -hash of the given public key or the segwit redeem hash generated from the -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.

-

Returns true if the address creates a particular script -This function doesn’t make any allocations.

-

Returns a reference to the checked address. -This function is dangerous in case the address is not a valid checked address.

-

Parsed addresses do not always have one network. The problem is that legacy testnet, -regtest and signet addresse use the same prefix instead of multiple different ones. When -parsing, such addresses are always assumed to be testnet addresses (the same is true for -bech32 signet addresses). So if one wants to check if an address belongs to a certain -network a simple comparison is not enough anymore. Instead this function can be used.

- -
use bitcoin::{Address, Network};
-use bitcoin::address::NetworkUnchecked;
-
-let address: Address<NetworkUnchecked> = "2N83imGV3gPwBzKJQvWJ7cRUY2SpUyU6A5e".parse().unwrap();
-assert!(address.is_valid_for_network(Network::Testnet));
-assert!(address.is_valid_for_network(Network::Regtest));
-assert!(address.is_valid_for_network(Network::Signet));
-
-assert_eq!(address.is_valid_for_network(Network::Bitcoin), false);
-
-let address: Address<NetworkUnchecked> = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap();
-assert!(address.is_valid_for_network(Network::Bitcoin));
-assert_eq!(address.is_valid_for_network(Network::Testnet), false);
-

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.

-

Calls U::from(self).

-

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

-
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 deleted file mode 100644 index e65432832d..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Balance.html +++ /dev/null @@ -1,22 +0,0 @@ -Balance in bdk::wallet - Rust

Struct bdk::wallet::Balance

source ·
pub struct Balance {
-    pub immature: Amount,
-    pub trusted_pending: Amount,
-    pub untrusted_pending: Amount,
-    pub confirmed: Amount,
-}
Expand description

Balance, differentiated into various categories.

-

Fields§

§immature: Amount

All coinbase outputs not yet matured

-
§trusted_pending: Amount

Unconfirmed UTXOs generated by a wallet tx

-
§untrusted_pending: Amount

Unconfirmed UTXOs received from an external wallet

-
§confirmed: Amount

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.ChangeSet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.ChangeSet.html deleted file mode 100644 index 700d6a03e0..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.ChangeSet.html +++ /dev/null @@ -1,16 +0,0 @@ -ChangeSet in bdk::wallet - Rust

Struct bdk::wallet::ChangeSet

source ·
pub struct ChangeSet {
-    pub chain: ChangeSet,
-    pub indexed_tx_graph: ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>,
-    pub network: Option<Network>,
-}
Expand description

The changes made to a wallet by applying an Update.

-

Fields§

§chain: ChangeSet

Changes to the LocalChain.

-
§indexed_tx_graph: ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>

Changes to IndexedTxGraph.

-
§network: Option<Network>

Stores the network type of the wallet.

-

Trait Implementations§

Append another object of the same type onto self.
Returns whether the structure is considered empty.
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.
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/wallet/struct.Update.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Update.html deleted file mode 100644 index d82464d8e7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Update.html +++ /dev/null @@ -1,16 +0,0 @@ -Update in bdk::wallet - Rust

Struct bdk::wallet::Update

source ·
pub struct Update {
-    pub last_active_indices: BTreeMap<KeychainKind, u32>,
-    pub graph: TxGraph<ConfirmationTimeHeightAnchor>,
-    pub chain: Option<CheckPoint>,
-}
Expand description

Fields§

§last_active_indices: BTreeMap<KeychainKind, u32>

Contains the last active derivation indices per keychain (K), which is used to update the -KeychainTxOutIndex.

-
§graph: TxGraph<ConfirmationTimeHeightAnchor>

Update for the wallet’s internal TxGraph.

-
§chain: Option<CheckPoint>

Update for the wallet’s internal LocalChain.

-

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
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 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/struct.Wallet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html deleted file mode 100644 index eb885b5bc5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html +++ /dev/null @@ -1,314 +0,0 @@ -Wallet in bdk::wallet - Rust

Struct bdk::wallet::Wallet

source ·
pub struct Wallet { /* private fields */ }
Expand description

A Bitcoin wallet

-

The Wallet 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. signers that can contribute signatures to addresses instantiated from the descriptors.
  4. -
-

Implementations§

Creates a wallet that does not persist data.

-

Creates a wallet that does not persist data, with a custom genesis hash.

-

Initialize an empty Wallet.

-

Initialize an empty Wallet with a custom genesis hash.

-

This is like Wallet::new with an additional genesis_hash parameter. This is useful -for syncing from alternative networks.

-

Load Wallet from the given persistence backend.

-

Note that the descriptor secret keys are not persisted to the db; this means that after -calling this method the Wallet won’t know the secret keys, and as such, won’t be -able to sign transactions.

-

If you wish to use the wallet to sign transactions, you need to add the secret keys -manually to the Wallet:

- -
let secp = Secp256k1::new();
-
-let (external_descriptor, external_keymap) = Descriptor::parse_descriptor(&secp, "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)").unwrap();
-let (internal_descriptor, internal_keymap) = Descriptor::parse_descriptor(&secp, "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)").unwrap();
-
-let external_signer_container = SignersContainer::build(external_keymap, &external_descriptor, &secp);
-let internal_signer_container = SignersContainer::build(internal_keymap, &internal_descriptor, &secp);
-
-let mut wallet = Wallet::load(db)?;
-
-external_signer_container.signers().into_iter()
-    .for_each(|s| wallet.add_signer(KeychainKind::External, SignerOrdering::default(), s.clone()));
-internal_signer_container.signers().into_iter()
-    .for_each(|s| wallet.add_signer(KeychainKind::Internal, SignerOrdering::default(), s.clone()));
-

Alternatively, you can call Wallet::new_or_load, which will add the private keys of the -passed-in descriptors to the Wallet.

-

Either loads Wallet from persistence, or initializes it if it does not exist.

-

This method will fail if the loaded Wallet has different parameters to those provided.

-

Either loads Wallet from persistence, or initializes it if it does not exist, using the -provided descriptor, change descriptor, network, and custom genesis hash.

-

This method will fail if the loaded Wallet has different parameters to those provided. -This is like Wallet::new_or_load with an additional genesis_hash parameter. This is -useful for syncing from alternative networks.

-

Get the Bitcoin network the wallet is using.

-

Iterator over all keychains in this wallet

-

Peek an address of the given keychain at index without revealing it.

-

For non-wildcard descriptors this returns the same address at every provided index.

-
Panics
-

This panics when the caller requests for an address of derivation index greater than the -BIP32 max index.

-

Attempt to reveal the next address of the given keychain.

-

This will increment the internal derivation index. If the keychain’s descriptor doesn’t -contain a wildcard or every address is already revealed up to the maximum derivation -index defined in BIP32, -then returns the last revealed address.

-
Errors
-

If writing to persistent storage fails.

-

Reveal addresses up to and including the target index and return an iterator -of newly revealed addresses.

-

If the target index is unreachable, we make a best effort to reveal up to the last -possible index. If all addresses up to the given index are already revealed, then -no new addresses are returned.

-
Errors
-

If writing to persistent storage fails.

-

Get the next unused address for the given keychain, i.e. the address with the lowest -derivation index that hasn’t been used.

-

This will attempt to derive and reveal a new address if no newly revealed addresses -are available. See also reveal_next_address.

-
Errors
-

If writing to persistent storage fails.

-

Marks an address used of the given keychain at index.

-

Returns whether the given index was present and then removed from the unused set.

-

Undoes the effect of mark_used and returns whether the index was inserted -back into the unused set.

-

Since this is only a superficial marker, it will have no effect if the address at the given -index was actually used, i.e. the wallet has previously indexed a tx output for the -derived spk.

-

List addresses that are revealed but unused.

-

Note if the returned iterator is empty you can reveal more addresses -by using reveal_next_address or -reveal_addresses_to.

-

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

-

List all relevant outputs (includes both spent and unspent, confirmed and unconfirmed).

-

To list only unspent outputs (UTXOs), use Wallet::list_unspent instead.

-

Get all the checkpoints the wallet is currently storing indexed by height.

-

Returns the latest checkpoint.

-

Get unbounded script pubkey iterators for both Internal and External keychains.

-

This is intended 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 gap.

-

Note carefully that iterators go over all script pubkeys on the keychains (not what -script pubkeys the wallet is storing internally).

-

Get an unbounded script pubkey iterator for the given keychain.

-

See all_unbounded_spk_iters for more documentation

-

Returns the utxo owned by this wallet corresponding to outpoint if it exists in the -wallet’s database.

-

Inserts a [TxOut] at [OutPoint] into the wallet’s transaction graph.

-

This is used for providing a previous output’s value so that we can use calculate_fee -or calculate_fee_rate on a given transaction. Outputs inserted with this method will -not be returned in list_unspent or list_output.

-

Any inserted TxOuts are not persisted until commit is called.

-

WARNING: This should only be used to add TxOuts that the wallet does not own. Only -insert TxOuts that you trust the values for!

-

Calculates the fee of a given transaction. Returns 0 if tx is a coinbase transaction.

-

To calculate the fee for a [Transaction] with inputs not owned by this wallet you must -manually insert the TxOut(s) into the tx graph using the insert_txout function.

-

Note tx does not have to be in the graph for this to work.

-
Examples
-
let tx = wallet.get_tx(txid).expect("transaction").tx_node.tx;
-let fee = wallet.calculate_fee(&tx).expect("fee");
- -
let tx = &psbt.clone().extract_tx().expect("tx");
-let fee = wallet.calculate_fee(tx).expect("fee");
-

Calculate the [FeeRate] for a given transaction.

-

To calculate the fee rate for a [Transaction] with inputs not owned by this wallet you must -manually insert the TxOut(s) into the tx graph using the insert_txout function.

-

Note tx does not have to be in the graph for this to work.

-
Examples
-
let tx = wallet.get_tx(txid).expect("transaction").tx_node.tx;
-let fee_rate = wallet.calculate_fee_rate(&tx).expect("fee rate");
- -
let tx = &psbt.clone().extract_tx().expect("tx");
-let fee_rate = wallet.calculate_fee_rate(tx).expect("fee rate");
-

Compute the tx’s sent and received [Amount]s.

-

This method returns a tuple (sent, received). Sent is the sum of the txin amounts -that spend from previous txouts tracked by this wallet. Received is the summation -of this tx’s outputs that send to script pubkeys tracked by this wallet.

-
Examples
-
let tx = wallet.get_tx(txid).expect("tx exists").tx_node.tx;
-let (sent, received) = wallet.sent_and_received(&tx);
- -
let tx = &psbt.clone().extract_tx().expect("tx");
-let (sent, received) = wallet.sent_and_received(tx);
-

Get a single transaction from the wallet as a CanonicalTx (if the transaction exists).

-

CanonicalTx contains the full transaction alongside meta-data such as:

-
    -
  • Blocks that the transaction is Anchored in. These may or may not be blocks that exist -in the best chain.
  • -
  • The ChainPosition of the transaction in the best chain - whether the transaction is -confirmed or unconfirmed. If the transaction is confirmed, the anchor which proves the -confirmation is provided. If the transaction is unconfirmed, the unix timestamp of when -the transaction was last seen in the mempool is provided.
  • -
- -
use bdk::{chain::ChainPosition, Wallet};
-use bdk_chain::Anchor;
-
-let canonical_tx = wallet.get_tx(my_txid).expect("panic if tx does not exist");
-
-// get reference to full transaction
-println!("my tx: {:#?}", canonical_tx.tx_node.tx);
-
-// list all transaction anchors
-for anchor in canonical_tx.tx_node.anchors {
-    println!(
-        "tx is anchored by block of hash {}",
-        anchor.anchor_block().hash
-    );
-}
-
-// get confirmation status of transaction
-match canonical_tx.chain_position {
-    ChainPosition::Confirmed(anchor) => println!(
-        "tx is confirmed at height {}, we know this since {}:{} is in the best chain",
-        anchor.confirmation_height, anchor.anchor_block.height, anchor.anchor_block.hash,
-    ),
-    ChainPosition::Unconfirmed(last_seen) => println!(
-        "tx is last seen at {}, it is unconfirmed as it is not anchored in the best chain",
-        last_seen,
-    ),
-}
-

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.

-

Returns whether anything changed with the transaction insertion (e.g. false if the -transaction was already inserted at the same position).

-

A tx can be rejected if position has a height greater than the latest_checkpoint. -Therefore you should use insert_checkpoint to insert new checkpoints before manually -inserting new transactions.

-

WARNING: If position is confirmed, we anchor the tx to a the lowest checkpoint that -is >= the position’s height. The caller is responsible for ensuring the tx exists in our -local view of the best chain’s history.

-

Iterate over the transactions in the wallet.

-

Return the balance, separated into available, trusted-pending, untrusted-pending and immature -values.

-

Add an external signer

-

See the signer module for an example.

-

Get the signers

-
Example
-
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.

-

This returns a blank TxBuilder from which you can specify the parameters for the transaction.

-
Example
-
let psbt = {
-   let mut builder =  wallet.build_tx();
-   builder
-       .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
-   builder.finish()?
-};
-
-// sign and broadcast ...
-

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.

-
Example
-
let mut psbt = {
-    let mut builder = wallet.build_tx();
-    builder
-        .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
-        .enable_rbf();
-    builder.finish()?
-};
-let _ = wallet.sign(&mut psbt, SignOptions::default())?;
-let tx = psbt.clone().extract_tx().expect("tx");
-// broadcast tx but it's taking too long to confirm so we want to bump the fee
-let mut psbt =  {
-    let mut builder = wallet.build_fee_bump(tx.txid())?;
-    builder
-        .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"));
-    builder.finish()?
-};
-
-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 -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 -signers will follow the options, but the “software signers” (WIF keys and xprv) defined -in this library will.

-
Example
-
let mut psbt = {
-    let mut builder = wallet.build_tx();
-    builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
-    builder.finish()?
-};
-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 -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 -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.

-

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

-

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 currently staged changed to the persistence backend returning and error when -this fails.

-

This returns whether the update resulted in any changes.

-

Returns the changes that will be committed with the next call to commit.

-

Get a reference to the inner TxGraph.

-

Get a reference to the inner KeychainTxOutIndex.

-

Get a reference to the inner LocalChain.

-

Introduces a block of height to the wallet, and tries to connect it to the -prev_blockhash of the block’s header.

-

This is a convenience method that is equivalent to calling apply_block_connected_to -with prev_blockhash and height-1 as the connected_to parameter.

-

Applies relevant transactions from block of height to the wallet, and connects the -block to the internal chain.

-

The connected_to parameter informs the wallet how this block connects to the internal -LocalChain. Relevant transactions are filtered from the block and inserted into the -internal TxGraph.

-

Apply relevant unconfirmed transactions to the wallet.

-

Transactions that are not relevant are filtered out.

-

This method takes in an iterator of (tx, last_seen) where last_seen is the timestamp of -when the transaction was last seen in the mempool. This is used for conflict resolution -when there is conflicting unconfirmed transactions. The transaction with the later -last_seen is prioritized.

-

Methods to construct sync/full-scan requests for spk-based chain sources.

-

Create a partial SyncRequest for this wallet for all revealed spks.

-

This is the first step when performing a spk-based wallet partial sync, the returned -SyncRequest collects all revealed script pubkeys from the wallet keychain needed to -start a blockchain sync with a spk based blockchain client.

-

Create a `FullScanRequest for this wallet.

-

This is the first step when performing a spk-based wallet full scan, the returned -`FullScanRequest collects iterators for the wallet’s keychain script pub keys needed to -start a blockchain full scan with a spk based blockchain client.

-

This operation is generally only used when importing or restoring a previously used wallet -in which the list of used scripts is not known.

-

Trait Implementations§

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 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/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html deleted file mode 100644 index bb8fa958d5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html +++ /dev/null @@ -1,8 +0,0 @@ -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 -keep it compatible with network dust rate

-

Required Methods§

Check whether or not a value is below dust limit

-

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.AddForeignUtxoError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.AddForeignUtxoError.html deleted file mode 100644 index 78aaa35010..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.AddForeignUtxoError.html +++ /dev/null @@ -1,20 +0,0 @@ -AddForeignUtxoError in bdk::wallet::tx_builder - Rust
pub enum AddForeignUtxoError {
-    InvalidTxid {
-        input_txid: Txid,
-        foreign_utxo: OutPoint,
-    },
-    InvalidOutpoint(OutPoint),
-    MissingUtxo,
-}
Expand description

Error returned from TxBuilder::add_foreign_utxo.

-

Variants§

§

InvalidTxid

Fields

§input_txid: Txid

PSBT input txid

-
§foreign_utxo: OutPoint

Foreign UTXO outpoint

-

Foreign utxo outpoint txid does not match PSBT input txid

-
§

InvalidOutpoint(OutPoint)

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

-
§

MissingUtxo

Foreign utxo missing witness_utxo or non_witness_utxo

-

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/tx_builder/enum.AddUtxoError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.AddUtxoError.html deleted file mode 100644 index 0778cb7653..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.AddUtxoError.html +++ /dev/null @@ -1,11 +0,0 @@ -AddUtxoError in bdk::wallet::tx_builder - Rust
pub enum AddUtxoError {
-    UnknownUtxo(OutPoint),
-}
Expand description

Error returned from TxBuilder::add_utxo and TxBuilder::add_utxos

-

Variants§

§

UnknownUtxo(OutPoint)

Happens when trying to spend an UTXO that is not in the internal database

-

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/tx_builder/enum.AllowShrinkingError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.AllowShrinkingError.html deleted file mode 100644 index 1be2155165..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.AllowShrinkingError.html +++ /dev/null @@ -1,11 +0,0 @@ -AllowShrinkingError in bdk::wallet::tx_builder - Rust
pub enum AllowShrinkingError {
-    MissingScriptPubKey(ScriptBuf),
-}
Expand description

Error returned from TxBuilder::allow_shrinking

-

Variants§

§

MissingScriptPubKey(ScriptBuf)

Script/PubKey was not in the original transaction

-

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/tx_builder/enum.ChangeSpendPolicy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html deleted file mode 100644 index 97491b23de..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html +++ /dev/null @@ -1,18 +0,0 @@ -ChangeSpendPolicy in bdk::wallet::tx_builder - Rust
pub enum ChangeSpendPolicy {
-    ChangeAllowed,
-    OnlyChange,
-    ChangeForbidden,
-}
Expand description

Policy regarding the use of change outputs when creating a transaction

-

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 -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
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 deleted file mode 100644 index 38398f4c11..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.TxOrdering.html +++ /dev/null @@ -1,19 +0,0 @@ -TxOrdering in bdk::wallet::tx_builder - Rust
pub enum TxOrdering {
-    Shuffle,
-    Untouched,
-    Bip69Lexicographic,
-}
Expand description

Ordering of the transaction’s inputs and outputs

-

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 -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
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 deleted file mode 100644 index ee155811ae..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/index.html +++ /dev/null @@ -1,18 +0,0 @@ -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();
-
-tx_builder
-    // Create a transaction with one output to `to_address` of 50_000 satoshi
-    .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
-    // With a custom fee rate of 5.0 satoshi/vbyte
-    .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
-    // Only spend non-change outputs
-    .do_not_spend_change()
-    // Turn on RBF signaling
-    .enable_rbf();
-let psbt = tx_builder.finish()?;
-

Structs

Marker type to indicate the TxBuilder is being used to bump the fee of an existing transaction.
Marker type to indicate the TxBuilder is being used to create a new transaction (as opposed -to bumping the fee of an existing one).
A transaction builder

Enums

Policy regarding the use of change outputs when creating a transaction
Ordering of the transaction’s inputs and outputs

Traits

Context in which the TxBuilder is valid
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/sidebar-items.js deleted file mode 100644 index abc3e92eca..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -window.SIDEBAR_ITEMS = {"enum":[["AddForeignUtxoError","Error returned from [`TxBuilder::add_foreign_utxo`]."],["AddUtxoError","Error returned from [`TxBuilder::add_utxo`] and [`TxBuilder::add_utxos`]"],["AllowShrinkingError","Error returned from [`TxBuilder::allow_shrinking`]"],["ChangeSpendPolicy","Policy regarding the use of change outputs when creating a transaction"],["TxOrdering","Ordering of the transaction’s inputs and outputs"]],"struct":[["BumpFee","Marker type to indicate the [`TxBuilder`] is being used to bump the fee of an existing transaction."],["CreateTx","Marker type to indicate the [`TxBuilder`] is being used to create a new transaction (as opposed to bumping the fee of an existing one)."],["TxBuilder","A transaction builder"]],"trait":[["TxBuilderContext","Context in which the [`TxBuilder`] is valid"]]}; \ No newline at end of file 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 deleted file mode 100644 index 02683f4913..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.BumpFee.html +++ /dev/null @@ -1,7 +0,0 @@ -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 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 deleted file mode 100644 index 60da472cf0..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.CreateTx.html +++ /dev/null @@ -1,8 +0,0 @@ -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.

-

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/wallet/tx_builder/struct.TxBuilder.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html deleted file mode 100644 index 6efb34e70e..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html +++ /dev/null @@ -1,244 +0,0 @@ -TxBuilder in bdk::wallet::tx_builder - Rust

Struct bdk::wallet::tx_builder::TxBuilder

source ·
pub struct TxBuilder<'a, 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.

-

Each option setting method on TxBuilder takes and returns &mut self so you can chain calls -as in the following example:

- -
// chaining
-let psbt1 = {
-    let mut builder = wallet.build_tx();
-    builder
-        .ordering(TxOrdering::Untouched)
-        .add_recipient(addr1.script_pubkey(), Amount::from_sat(50_000))
-        .add_recipient(addr2.script_pubkey(), Amount::from_sat(50_000));
-    builder.finish()?
-};
-
-// non-chaining
-let psbt2 = {
-    let mut builder = wallet.build_tx();
-    builder.ordering(TxOrdering::Untouched);
-    for addr in &[addr1, addr2] {
-        builder.add_recipient(addr.script_pubkey(), Amount::from_sat(50_000));
-    }
-    builder.finish()?
-};
-
-assert_eq!(psbt1.unsigned_tx.output[..2], psbt2.unsigned_tx.output[..2]);
-

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.

-

This method sets the mining fee paid by the transaction as a rate on its size. -This means that the total fee paid is equal to fee_rate times the size -of the transaction. Default is 1 sat/vB in accordance with Bitcoin Core’s default -relay policy.

-

Note that this is really a minimum feerate – it’s possible to -overshoot it slightly since adding a change output to drain the remaining -excess might not be viable.

-

Set an absolute fee -The fee_absolute method refers to the absolute transaction fee in satoshis (sats). -If anyone sets both the fee_absolute method and the fee_rate method, -the FeePolicy enum will be set by whichever method was called last, -as the FeeRate and FeeAmount are mutually exclusive.

-

Note that this is really a minimum absolute fee – it’s possible to -overshoot it slightly since adding a change output to drain the remaining -excess might not be viable.

-

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 -SatisfiableItem::Thresh::items).

-
Example
-

An example of when the policy path is needed is the following descriptor: -wsh(thresh(2,pk(A),sj:and_v(v:pk(B),n:older(6)),snj:and_v(v:pk(C),after(630000)))), -derived from the miniscript policy thresh(2,pk(A),and(pk(B),older(6)),and(pk(C),after(630000))). -It declares three descriptor fragments, and at the top level it uses thresh() to -ensure that at least two of them are satisfied. The individual fragments are:

-
    -
  1. pk(A)
  2. -
  3. and(pk(B),older(6))
  4. -
  5. and(pk(C),after(630000))
  6. -
-

When those conditions are combined in pairs, it’s clear that the transaction needs to be created -differently depending on how the user intends to satisfy the policy afterwards:

-
    -
  • If fragments 1 and 2 are used, the transaction will need to use a specific -n_sequence in order to spend an OP_CSV branch.
  • -
  • If fragments 1 and 3 are used, the transaction will need to use a specific locktime -in order to spend an OP_CLTV branch.
  • -
  • If fragments 2 and 3 are used, the transaction will need both.
  • -
-

When the spending policy is represented as a tree (see -Wallet::policies), every node -is assigned a unique identifier that can be used in the policy path to specify which of -the node’s children the user intends to satisfy: for instance, assuming the thresh() -root node of this example has an id of aabbccdd, the policy path map would look like:

-

{ "aabbccdd" => [0, 1] }

-

where the key is the node’s id, and the value is a list of the children that should be -used, in no particular order.

-

If a particularly complex descriptor has multiple ambiguous thresholds in its structure, -multiple entries can be added to the map, one for each node that requires an explicit path.

- -
Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
-    .unwrap()
-    .assume_checked();
-let mut path = BTreeMap::new();
-path.insert("aabbccdd".to_string(), vec![0, 1]);
-
-let builder = wallet
-    .build_tx()
-    .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
-    .policy_path(path, KeychainKind::External);
-
-

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

-

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.

-

At a minimum to add a foreign UTXO we need:

-
    -
  1. outpoint: To add it to the raw transaction.
  2. -
  3. psbt_input: To know the value.
  4. -
  5. satisfaction_weight: To know how much weight/vbytes the input will add to the transaction for fee calculation.
  6. -
-

There are several security concerns about adding foreign UTXOs that application -developers should consider. First, how do you know the value of the input is correct? If a -non_witness_utxo is provided in the psbt_input then this method implicitly verifies the -value by checking it against the transaction. If only a witness_utxo is provided then this -method doesn’t verify the value but just takes it as a given – it is up to you to check -that whoever sent you the input_psbt was not lying!

-

Secondly, you must somehow provide satisfaction_weight of the input. Depending on your -application it may be important that this be known precisely. If not, a malicious -counterparty may fool you into putting in a value that is too low, giving the transaction a -lower than expected feerate. They could also fool you into putting a value that is too high -causing you to pay a fee that is too high. The party who is broadcasting the transaction can -of course check the real input weight matches the expected weight prior to broadcasting.

-

To guarantee the max_weight_to_satisfy is correct, you can require the party providing the -psbt_input provide a miniscript descriptor for the input so you can check it against the -script_pubkey and then ask it for the max_weight_to_satisfy.

-

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

-

In order to use Wallet::calculate_fee or Wallet::calculate_fee_rate for a transaction -created with foreign UTXO(s) you must manually insert the corresponding TxOut(s) into the tx -graph using the Wallet::insert_txout function.

-
Errors
-

This method returns errors in the following circumstances:

-
    -
  1. The psbt_input does not contain a witness_utxo or non_witness_utxo.
  2. -
  3. The data in non_witness_utxo does not match what is in outpoint.
  4. -
-

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.

-

Same as add_foreign_utxo but allows to set the nSequence value.

-

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

-

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

-

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

-

Use this option very carefully

-

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

-

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

-

This effectively adds all the change outputs to the “unspendable” list. See -TxBuilder::unspendable.

-

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 -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 -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 -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

-

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.

-

Enable signaling RBF

-

This will use the default nSequence value of 0xFFFFFFFD.

-

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.

-

This will be used to:

-
    -
  1. Set the nLockTime for preventing fee sniping. -Note: This will be ignored if you manually specify a nlocktime using TxBuilder::nlocktime.
  2. -
  3. Decide whether coinbase outputs are mature or not. If the coinbase outputs are not -mature at current_height, we ignore them in the coin selection. -If you want to create a transaction that spends immature coinbase inputs, manually -add them using TxBuilder::add_utxos.
  4. -
-

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.

-

Note: by avoiding a dust limit check you may end up with a transaction that is non-standard.

-

Finish building the transaction.

-

Returns a new [Psbt] per BIP174.

-

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 -coins are too small) it will not be included in the resulting transaction. The only -difference is that it is valid to use drain_to without setting any ordinary recipients -with add_recipient (but it is perfectly fine to add recipients as well).

-

If you choose not to set any recipients, you should either provide the utxos that the -transaction should spend via add_utxos, or set drain_wallet to spend all of them.

-

When bumping the fees of a transaction made with this option, you probably want to -use allow_shrinking to allow this output to be reduced to pay for the extra fees.

-
Example
-

drain_to is very useful for draining all the coins in a wallet with drain_wallet to a -single address.

- -
Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
-    .unwrap()
-    .assume_checked();
-let mut tx_builder = wallet.build_tx();
-
-tx_builder
-    // Spend all outputs in this wallet.
-    .drain_wallet()
-    // Send the excess (which is all the coins minus the fee) to this address.
-    .drain_to(to_address.script_pubkey())
-    .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
-    .enable_rbf();
-let psbt = tx_builder.finish()?;
-

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 -preserved then it is currently not guaranteed to be in the same position as it was -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.

-

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/wallet/tx_builder/trait.TxBuilderContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html deleted file mode 100644 index dd22a0a1a9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html +++ /dev/null @@ -1,3 +0,0 @@ -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/utils/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/utils/trait.IsDust.html deleted file mode 100644 index c0e56858e7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/utils/trait.IsDust.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

Redirecting to ../../../bdk/wallet/trait.IsDust.html...

- - - \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.BlockEvent.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.BlockEvent.html index 8c40bf3c0f..96fa8fd92c 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.BlockEvent.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.BlockEvent.html @@ -1,18 +1,18 @@ BlockEvent in bdk_bitcoind_rpc - Rust
pub struct BlockEvent<B> {
     pub block: B,
-    pub checkpoint: CheckPoint,
+    pub checkpoint: CheckPoint,
 }
Expand description

A newly emitted block from Emitter.

Fields§

§block: B

Either a full [Block] or [Header] of the new block.

-
§checkpoint: CheckPoint

The checkpoint of the new block.

-

A CheckPoint is a node of a linked list of BlockIds. This checkpoint is linked to -all BlockIds originally passed in Emitter::new as well as emitted blocks since then. +

§checkpoint: CheckPoint

The checkpoint of the new block.

+

A [CheckPoint] is a node of a linked list of [BlockId]s. This checkpoint is linked to +all [BlockId]s originally passed in Emitter::new as well as emitted blocks since then. These blocks are guaranteed to be of the same chain.

This is important as BDK structures require block-to-apply to be connected with another block in the original chain.

Implementations§

The block height of this new block.

The block hash of this new block.

-

The BlockId of a previous block that this block connects to.

-

This either returns a BlockId of a previously emitted block or from the chain we started +

The [BlockId] of a previous block that this block connects to.

+

This either returns a [BlockId] of a previously emitted block or from the chain we started with (passed in as last_cp in Emitter::new).

This value is derived from BlockEvent::checkpoint.

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.

diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.Emitter.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.Emitter.html index aec3eeb9e3..f18b7bc898 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.Emitter.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.Emitter.html @@ -1,6 +1,6 @@ Emitter in bdk_bitcoind_rpc - Rust

Struct bdk_bitcoind_rpc::Emitter

source ·
pub struct Emitter<'c, C> { /* private fields */ }
Expand description

The Emitter is used to emit data sourced from [bitcoincore_rpc::Client].

Refer to module-level documentation for more.

-

Implementations§

Construct a new Emitter.

+

Implementations§

Construct a new Emitter.

last_cp informs the emitter of the chain we are starting off with. This way, the emitter can start emission from a block that connects to the original chain.

start_height starts emission from a given height (if there are no conflicts with the 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 index ab0b3598fe..4bcf1c54f5 100644 --- 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 @@ -1,4 +1,4 @@ -bdk_electrum - Rust

Crate bdk_electrum

source ·
Expand description

This crate is used for updating structures of bdk_chain with data from an Electrum server.

+bdk_electrum - Rust

Crate bdk_electrum

source ·
Expand description

This crate is used for updating structures of [bdk_chain] with data from an Electrum server.

The two primary methods are ElectrumExt::sync and ElectrumExt::full_scan. In most cases ElectrumExt::sync is used to sync the transaction histories of scripts that the application cares about, for example the scripts for all the receive addresses of a Wallet’s keychain that it @@ -6,6 +6,6 @@ has shown a user. bdk_chain.

+[bdk_chain].

Refer to example_electrum 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 +

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/struct.ElectrumFullScanResult.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumFullScanResult.html index e505b22049..40e9984ee0 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumFullScanResult.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumFullScanResult.html @@ -1,8 +1,8 @@ ElectrumFullScanResult in bdk_electrum - Rust
pub struct ElectrumFullScanResult<K>(_);
Expand description

The result of ElectrumExt::full_scan.

-

This can be transformed into a FullScanResult with either ConfirmationHeightAnchor or -ConfirmationTimeHeightAnchor anchor types.

-

Implementations§

Return FullScanResult with ConfirmationTimeHeightAnchor.

+

This can be transformed into a [FullScanResult] with either [ConfirmationHeightAnchor] or +[ConfirmationTimeHeightAnchor] anchor types.

+

Implementations§

Return [FullScanResult] with [ConfirmationHeightAnchor].

+

Return [FullScanResult] with [ConfirmationTimeHeightAnchor].

This requires additional calls to the Electrum server.

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).

diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumSyncResult.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumSyncResult.html index 27b17697e1..36acaf655a 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumSyncResult.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumSyncResult.html @@ -1,8 +1,8 @@ ElectrumSyncResult in bdk_electrum - Rust
pub struct ElectrumSyncResult(_);
Expand description

The result of ElectrumExt::sync.

-

This can be transformed into a SyncResult with either ConfirmationHeightAnchor or -ConfirmationTimeHeightAnchor anchor types.

-

Implementations§

Return SyncResult with ConfirmationTimeHeightAnchor.

+

This can be transformed into a [SyncResult] with either [ConfirmationHeightAnchor] or +[ConfirmationTimeHeightAnchor] anchor types.

+

Implementations§

Return [SyncResult] with [ConfirmationHeightAnchor].

+

Return [SyncResult] with [ConfirmationTimeHeightAnchor].

This requires additional calls to the Electrum server.

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).

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 index 2f942acd17..78de604959 100644 --- 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 @@ -1,12 +1,12 @@ ElectrumExt in bdk_electrum - Rust
pub trait ElectrumExt {
-    fn full_scan<K: Ord + Clone>(
        &self,
        request: FullScanRequest<K>,
        stop_gap: usize,
        batch_size: usize,
        fetch_prev_txouts: bool
    ) -> Result<ElectrumFullScanResult<K>, Error>; - fn sync(
        &self,
        request: SyncRequest,
        batch_size: usize,
        fetch_prev_txouts: bool
    ) -> Result<ElectrumSyncResult, Error>; + fn full_scan<K: Ord + Clone>(
        &self,
        request: FullScanRequest<K>,
        stop_gap: usize,
        batch_size: usize,
        fetch_prev_txouts: bool
    ) -> Result<ElectrumFullScanResult<K>, Error>; + fn sync(
        &self,
        request: SyncRequest,
        batch_size: usize,
        fetch_prev_txouts: bool
    ) -> Result<ElectrumSyncResult, Error>; }
Expand description

Trait to extend [electrum_client::Client] functionality.

-

Required Methods§

Full scan the keychain scripts specified with the blockchain (via an Electrum client) and -returns updates for bdk_chain data structures.

+

Required Methods§

Full scan the keychain scripts specified with the blockchain (via an Electrum client) and +returns updates for [bdk_chain] data structures.

  • request: struct with data required to perform a spk-based blockchain client full scan, -see FullScanRequest
  • +see [FullScanRequest]
  • stop_gap: the full scan for each keychain stops after a gap of script pubkeys with no associated transactions
  • batch_size: specifies the max number of script pubkeys to request for in a single batch @@ -14,11 +14,11 @@ request
  • fetch_prev_txouts: specifies whether or not we want previous TxOuts for fee calculation
-

Sync a set of scripts with the blockchain (via an Electrum client) for the data specified -and returns updates for bdk_chain data structures.

+

Sync a set of scripts with the blockchain (via an Electrum client) for the data specified +and returns updates for [bdk_chain] data structures.

  • request: struct with data required to perform a spk-based blockchain client sync, -see SyncRequest
  • +see [SyncRequest]
  • batch_size: specifies the max number of script pubkeys to request for in a single batch request
  • fetch_prev_txouts: specifies whether or not we want previous TxOuts for fee 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 index 6ae2f57f67..f7cfad39e8 100644 --- 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 @@ -27,6 +27,6 @@ has shown a user. bdk_chain -via a new TxGraph to be appended to any existing TxGraph data.

    +via a new TxGraph to be appended to any existing TxGraph data.

    Refer to example_esplora for a complete example.

Re-exports

pub use esplora_client;

Traits

Trait to extend the functionality of [esplora_client::AsyncClient].
Trait to extend the functionality of [esplora_client::BlockingClient].

Type Definitions

[esplora_client::Error]
\ 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 index 574dcad981..4a69627be0 100644 --- 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 @@ -1,13 +1,13 @@ EsploraAsyncExt in bdk_esplora - Rust
pub trait EsploraAsyncExt {
-    fn full_scan<'life0, 'async_trait, K>(
        &'life0 self,
        request: FullScanRequest<K>,
        stop_gap: usize,
        parallel_requests: usize
    ) -> Pin<Box<dyn Future<Output = Result<FullScanResult<K>, Box<Error>>> + Send + 'async_trait>>
    where
        K: 'async_trait + Ord + Clone + Send,
        Self: 'async_trait,
        'life0: 'async_trait
; - fn sync<'life0, 'async_trait>(
        &'life0 self,
        request: SyncRequest,
        parallel_requests: usize
    ) -> Pin<Box<dyn Future<Output = Result<SyncResult, Box<Error>>> + Send + 'async_trait>>
    where
        Self: 'async_trait,
        'life0: 'async_trait
; + fn full_scan<'life0, 'async_trait, K>(
        &'life0 self,
        request: FullScanRequest<K>,
        stop_gap: usize,
        parallel_requests: usize
    ) -> Pin<Box<dyn Future<Output = Result<FullScanResult<K>, Box<Error>>> + Send + 'async_trait>>
    where
        K: 'async_trait + Ord + Clone + Send,
        Self: 'async_trait,
        'life0: 'async_trait
; + fn sync<'life0, 'async_trait>(
        &'life0 self,
        request: SyncRequest,
        parallel_requests: usize
    ) -> Pin<Box<dyn Future<Output = Result<SyncResult, Box<Error>>> + Send + 'async_trait>>
    where
        Self: 'async_trait,
        'life0: 'async_trait
; }
Expand description

Trait to extend the functionality of [esplora_client::AsyncClient].

Refer to crate-level documentation for more.

-

Required Methods§

Scan keychain scripts for transactions against Esplora, returning an update that can be +

Required Methods§

Scan keychain scripts for transactions against Esplora, returning an update that can be applied to the receiving structures.

  • request: struct with data required to perform a spk-based blockchain client full scan, -see FullScanRequest
  • +see [FullScanRequest]

The full 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 @@ -21,12 +21,12 @@ such as BTCPay Server, and Sparrow.

A stop_gap of 0 will be treated as a stop_gap of 1.

-

Sync a set of scripts with the blockchain (via an Esplora client) for the data -specified and return a TxGraph.

+

Sync a set of scripts with the blockchain (via an Esplora client) for the data +specified and return a [TxGraph].

  • request: struct with data required to perform a spk-based blockchain client sync, see -SyncRequest
  • +[SyncRequest]

If the scripts to sync are unknown, such as when restoring or importing a keychain that may include scripts that have been used, use full_scan with the keychain.

-

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_esplora/trait.EsploraExt.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraExt.html index f65d8becd2..0fafa3a844 100644 --- 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 @@ -1,13 +1,13 @@ EsploraExt in bdk_esplora - Rust

Trait bdk_esplora::EsploraExt

source ·
pub trait EsploraExt {
-    fn full_scan<K: Ord + Clone>(
        &self,
        request: FullScanRequest<K>,
        stop_gap: usize,
        parallel_requests: usize
    ) -> Result<FullScanResult<K>, Error>; - fn sync(
        &self,
        request: SyncRequest,
        parallel_requests: usize
    ) -> Result<SyncResult, Error>; + fn full_scan<K: Ord + Clone>(
        &self,
        request: FullScanRequest<K>,
        stop_gap: usize,
        parallel_requests: usize
    ) -> Result<FullScanResult<K>, Error>; + fn sync(
        &self,
        request: SyncRequest,
        parallel_requests: usize
    ) -> Result<SyncResult, Error>; }
Expand description

Trait to extend the functionality of [esplora_client::BlockingClient].

Refer to crate-level documentation for more.

-

Required Methods§

Scan keychain scripts for transactions against Esplora, returning an update that can be +

Required Methods§

Scan keychain scripts for transactions against Esplora, returning an update that can be applied to the receiving structures.

  • request: struct with data required to perform a spk-based blockchain client full scan, -see FullScanRequest
  • +see [FullScanRequest]

The full 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 @@ -21,12 +21,12 @@ such as BTCPay Server, and Sparrow.

A stop_gap of 0 will be treated as a stop_gap of 1.

-

Sync a set of scripts with the blockchain (via an Esplora client) for the data -specified and return a TxGraph.

+

Sync a set of scripts with the blockchain (via an Esplora client) for the data +specified and return a [TxGraph].

  • request: struct with data required to perform a spk-based blockchain client sync, see -SyncRequest
  • +[SyncRequest]

If the scripts to sync are unknown, such as when restoring or importing a keychain that may include scripts that have been used, use full_scan with the keychain.

-

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_file_store/struct.Store.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/struct.Store.html index 43c6a0b49d..61812f1c88 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/struct.Store.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_file_store/struct.Store.html @@ -1,5 +1,5 @@ Store in bdk_file_store - Rust

Struct bdk_file_store::Store

source ·
pub struct Store<C>where
    C: Sync + Send,
{ /* private fields */ }
Expand description

Persists an append-only list of changesets (C) to a single file.

-

Implementations§

Create a new Store file in write-only mode; error if the file exists.

+

Implementations§

Create a new Store file in write-only mode; error if the file exists.

magic is the prefixed bytes to write to the new file. This will be checked when opening the Store in the future with open.

Open an existing Store.

@@ -29,7 +29,7 @@ changeset will be written over the erroring entry (or the end of the file if non 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
Writes a changeset to the persistence backend. Read more
Return the aggregate changeset C from persistence.

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
Writes a changeset to the persistence backend. Read more
Return the aggregate changeset C from persistence.

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.

diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_hwi/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_hwi/index.html index 67df392037..64e92c30ef 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_hwi/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_hwi/index.html @@ -1,5 +1,5 @@ bdk_hwi - Rust

Crate bdk_hwi

source ·
Expand description

HWI Signer

-

This crate contains HWISigner, an implementation of a TransactionSigner to be +

This crate contains HWISigner, an implementation of a TransactionSigner to be used with hardware wallets.

let mut devices = HWIClient::enumerate()?;
diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_persist/struct.Persist.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_persist/struct.Persist.html
index a0eda7aa30..8359a9626a 100644
--- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_persist/struct.Persist.html
+++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_persist/struct.Persist.html
@@ -3,7 +3,7 @@ before they are persisted.

Not all changes to the in-memory representation needs to be written to disk right away, so Persist::stage can be used to stage changes first and then Persist::commit can be used to write changes to disk.

-

Implementations§

Create a new Persist from PersistBackend.

+

Implementations§

Create a new Persist from PersistBackend.

Stage a changeset to be committed later with commit.

Get the changes that have not been committed yet.

Commit the staged changes to the underlying persistence backend.

diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/all.html new file mode 100644 index 0000000000..52a72a9f1e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/all.html @@ -0,0 +1,2 @@ +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_wallet/descriptor/checksum/fn.calc_checksum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/checksum/fn.calc_checksum.html new file mode 100644 index 0000000000..6948110a7a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/checksum/fn.calc_checksum.html @@ -0,0 +1,3 @@ +calc_checksum in bdk_wallet::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_wallet/descriptor/checksum/fn.calc_checksum_bytes.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/checksum/fn.calc_checksum_bytes.html new file mode 100644 index 0000000000..c359bae810 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/checksum/fn.calc_checksum_bytes.html @@ -0,0 +1,3 @@ +calc_checksum_bytes in bdk_wallet::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_wallet/descriptor/checksum/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/checksum/index.html new file mode 100644 index 0000000000..ab6975cd0f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/checksum/index.html @@ -0,0 +1,5 @@ +bdk_wallet::descriptor::checksum - Rust
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
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/checksum/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/checksum/sidebar-items.js new file mode 100644 index 0000000000..c3609de7d4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/checksum/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"fn":[["calc_checksum","Compute the checksum of a descriptor, excludes any existing checksum in the descriptor string from the calculation"],["calc_checksum_bytes","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_wallet/descriptor/enum.Descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/enum.Descriptor.html new file mode 100644 index 0000000000..c790fe32b6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/enum.Descriptor.html @@ -0,0 +1,190 @@ +Descriptor in bdk_wallet::descriptor - Rust
pub enum Descriptor<Pk>where
    Pk: MiniscriptKey,
{ + Bare(Bare<Pk>), + Pkh(Pkh<Pk>), + Wpkh(Wpkh<Pk>), + Sh(Sh<Pk>), + Wsh(Wsh<Pk>), + Tr(Tr<Pk>), +}
Expand description

Script descriptor

+

Variants§

§

Bare(Bare<Pk>)

A raw scriptpubkey (including pay-to-pubkey) under Legacy context

+
§

Pkh(Pkh<Pk>)

Pay-to-PubKey-Hash

+
§

Wpkh(Wpkh<Pk>)

Pay-to-Witness-PubKey-Hash

+
§

Sh(Sh<Pk>)

Pay-to-ScriptHash(includes nested wsh/wpkh/sorted multi)

+
§

Wsh(Wsh<Pk>)

Pay-to-Witness-ScriptHash with Segwitv0 context

+
§

Tr(Tr<Pk>)

Pay-to-Taproot

+

Implementations§

Create a new pk descriptor

+

Create a new PkH descriptor

+

Create a new Wpkh descriptor +Will return Err if uncompressed key is used

+

Create a new sh wrapped wpkh from Pk. +Errors when uncompressed keys are supplied

+

Create a new sh for a given redeem script +Errors when miniscript exceeds resource limits under p2sh context +or does not type check at the top level

+

Create a new wsh descriptor from witness script +Errors when miniscript exceeds resource limits under p2sh context +or does not type check at the top level

+

Create a new sh wrapped wsh descriptor with witness script +Errors when miniscript exceeds resource limits under wsh context +or does not type check at the top level

+

Create a new bare descriptor from witness script +Errors when miniscript exceeds resource limits under bare context +or does not type check at the top level

+

Create a new sh wrapper for the given wpkh descriptor

+

Create a new sh wrapper for the given wsh descriptor

+

Create a new sh sortedmulti descriptor with threshold k +and Vec of pks. +Errors when miniscript exceeds resource limits under p2sh context

+

Create a new sh wrapped wsh sortedmulti descriptor from threshold +k and Vec of pks +Errors when miniscript exceeds resource limits under segwit context

+

Create a new wsh sorted multi descriptor +Errors when miniscript exceeds resource limits under p2sh context

+

Create new tr descriptor +Errors when miniscript exceeds resource limits under Tap context

+

Get the [DescriptorType] of Descriptor

+

Checks whether the descriptor is safe.

+

Checks whether all the spend paths in the descriptor are possible on the +bitcoin network under the current standardness and consensus rules. Also +checks whether the descriptor requires signatures on all spend paths and +whether the script is malleable.

+

In general, all the guarantees of miniscript hold only for safe scripts. +The signer may not be able to find satisfactions even if one exists.

+

Computes an upper bound on the difference between a non-satisfied +TxIn’s segwit_weight and a satisfied TxIn’s segwit_weight

+

Since this method uses segwit_weight instead of legacy_weight, +if you want to include only legacy inputs in your transaction, +you should remove 1WU from each input’s max_weight_to_satisfy +for a more accurate estimate.

+

In other words, for segwit inputs or legacy inputs included in +segwit transactions, the following will hold for each input if +that input was satisfied with the largest possible witness:

+ +
ⓘ
for i in 0..transaction.input.len() {
+    assert_eq!(
+        descriptor_for_input[i].max_weight_to_satisfy(),
+        transaction.input[i].segwit_weight() - TxIn::default().segwit_weight()
+    );
+}
+

Instead, for legacy transactions, the following will hold for each input +if that input was satisfied with the largest possible witness:

+ +
ⓘ
for i in 0..transaction.input.len() {
+    assert_eq!(
+        descriptor_for_input[i].max_weight_to_satisfy(),
+        transaction.input[i].legacy_weight() - TxIn::default().legacy_weight()
+    );
+}
+

Assumes all ECDSA signatures are 73 bytes, including push opcode and +sighash suffix. +Assumes all Schnorr signatures are 66 bytes, including push opcode and +sighash suffix.

+
Errors
+

When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).

+
👎Deprecated: use max_weight_to_satisfy instead

Computes an upper bound on the weight of a satisfying witness to the +transaction.

+

Assumes all ec-signatures are 73 bytes, including push opcode and +sighash suffix. Includes the weight of the VarInts encoding the +scriptSig and witness stack length.

+
Errors
+

When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).

+

Computes the Bitcoin address of the descriptor, if one exists

+

Some descriptors like pk() don’t have an address.

+
Errors
+

For raw/bare descriptors that don’t have an address.

+

Computes the scriptpubkey of the descriptor.

+

Computes the scriptSig that will be in place for an unsigned input +spending an output with this descriptor. For pre-segwit descriptors, +which use the scriptSig for signatures, this returns the empty script.

+

This is used in Segwit transactions to produce an unsigned transaction +whose txid will not change during signing (since only the witness data +will change).

+

Computes the the underlying script before any hashing is done. For +Bare, Pkh and Wpkh this is the scriptPubkey; for ShWpkh and Sh +this is the redeemScript; for the others it is the witness script.

+
Errors
+

If the descriptor is a taproot descriptor.

+

Computes the scriptCode of a transaction output.

+

The scriptCode is the Script of the previous transaction output being +serialized in the sighash when evaluating a CHECKSIG & co. OP code.

+
Errors
+

If the descriptor is a taproot descriptor.

+

Returns satisfying non-malleable witness and scriptSig to spend an +output controlled by the given descriptor if it possible to +construct one using the satisfier S.

+

Returns a possilbly mallable satisfying non-malleable witness and scriptSig to spend an +output controlled by the given descriptor if it possible to +construct one using the satisfier S.

+

Attempts to produce a non-malleable satisfying witness and scriptSig to spend an +output controlled by the given descriptor; add the data to a given +TxIn output.

+

Returns a plan if the provided assets are sufficient to produce a non-malleable satisfaction

+

If the assets aren’t sufficient for generating a Plan, the descriptor is returned

+

Returns a plan if the provided assets are sufficient to produce a malleable satisfaction

+

If the assets aren’t sufficient for generating a Plan, the descriptor is returned

+
👎Deprecated: use has_wildcards instead

Whether or not the descriptor has any wildcards

+

Whether or not the descriptor has any wildcards i.e. /*.

+

Replaces all wildcards (i.e. /*) in the descriptor with a particular derivation index, +turning it into a definite descriptor.

+
Errors
+
    +
  • If index ≥ 2^31
  • +
+
👎Deprecated: use at_derivation_index instead

Deprecated name for Self::at_derivation_index.

+

Convert all the public keys in the descriptor to [bitcoin::PublicKey] by deriving them or +otherwise converting them. All [bitcoin::secp256k1::XOnlyPublicKey]s are converted to by adding a +default(0x02) y-coordinate.

+

This is a shorthand for:

+ +
    .expect("Valid ranged descriptor");
+let derived_descriptor = descriptor.at_derivation_index(index).unwrap().derived_descriptor(&secp).unwrap();
+

and is only here really here for backwards compatbility. +See at_derivation_index and [derived_descriptor] for more documentation.

+
Errors
+

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

+

Parse a descriptor that may contain secret keys

+

Internally turns every secret key found into the corresponding public key and then returns a +a descriptor that only contains public keys and a map to lookup the secret key given a public key.

+

Serialize a descriptor to string with its secret keys

+

Utility method for deriving the descriptor at each index in a range to find one matching +script_pubkey.

+

If it finds a match then it returns the index it was derived at and the concrete +descriptor at that index. If the descriptor is non-derivable then it will simply check the +script pubkey against the descriptor and return it if it matches (in this case the index +returned will be meaningless).

+

Whether this descriptor contains a key that has multiple derivation paths.

+

Get as many descriptors as different paths in this descriptor.

+

For multipath descriptors it will return as many descriptors as there is +“parallel” paths. For regular descriptors it will just return itself.

+

Convert all the public keys in the descriptor to [bitcoin::PublicKey] by deriving them or +otherwise converting them. All [bitcoin::secp256k1::XOnlyPublicKey]s are converted to by adding a +default(0x02) y-coordinate.

+
Examples
+
use miniscript::descriptor::{Descriptor, DescriptorPublicKey};
+use miniscript::bitcoin::secp256k1;
+use std::str::FromStr;
+
+// test from bip 86
+let secp = secp256k1::Secp256k1::verification_only();
+let descriptor = Descriptor::<DescriptorPublicKey>::from_str("tr(xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/*)")
+    .expect("Valid ranged descriptor");
+let result = descriptor.at_derivation_index(0).unwrap().derived_descriptor(&secp).expect("Non-hardened derivation");
+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
Returns the minimum value (in satoshis) at which an output is broadcastable. +Panics if the descriptor wildcard is hardened. Read more
Returns the descriptor id, calculated as the sha256 of the descriptor, checksum not +included. 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
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
Converts this 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.

+

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/descriptor/enum.DescriptorPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/enum.DescriptorPublicKey.html new file mode 100644 index 0000000000..c54c93e2c4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/enum.DescriptorPublicKey.html @@ -0,0 +1,55 @@ +DescriptorPublicKey in bdk_wallet::descriptor - Rust
pub enum DescriptorPublicKey {
+    Single(SinglePub),
+    XPub(DescriptorXKey<Xpub>),
+    MultiXPub(DescriptorMultiXKey<Xpub>),
+}
Expand description

The descriptor pubkey, either a single pubkey or an xpub.

+

Variants§

§

Single(SinglePub)

Single public key.

+
§

XPub(DescriptorXKey<Xpub>)

Extended public key (xpub).

+
§

MultiXPub(DescriptorMultiXKey<Xpub>)

Multiple extended public keys.

+

Implementations§

The fingerprint of the master key associated with this key, 0x00000000 if none.

+

Full path, from the master key

+

For wildcard keys this will return the path up to the wildcard, so you +can get full paths by appending one additional derivation step, according +to the wildcard type (hardened or normal).

+

For multipath extended keys, this returns None.

+

Returns a vector containing the full derivation paths from the master key. +The vector will contain just one element for single keys, and multiple elements +for multipath extended keys.

+

For wildcard keys this will return the path up to the wildcard, so you +can get full paths by appending one additional derivation step, according +to the wildcard type (hardened or normal).

+
👎Deprecated: use has_wildcard instead

Whether or not the key has a wildcard

+

Whether or not the key has a wildcard

+
👎Deprecated: use at_derivation_index instead

Deprecated name for Self::at_derivation_index.

+

Replaces any wildcard (i.e. /*) in the key with a particular derivation index, turning it into a +definite key (i.e. one where all the derivation paths are set).

+
Returns
+
    +
  • If this key is not an xpub, returns self.
  • +
  • If this key is an xpub but does not have a wildcard, returns self.
  • +
  • Otherwise, returns the xpub at derivation index (removing the wildcard).
  • +
+
Errors
+
    +
  • If index is hardened.
  • +
+

Whether or not this key has multiple derivation paths.

+

Get as many keys as derivation paths in this key.

+

For raw public key and single-path extended keys it will return the key itself. +For multipath extended keys it will return a single-path extended key per derivation +path.

+

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
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
Convert self into a Assets struct
Turn the key into a DescriptorKey within the requested ScriptContext
The associated [bitcoin::hashes::sha256::Hash] for this [MiniscriptKey], used in the +sha256 fragment. Read more
The associated [miniscript::hash256::Hash] for this [MiniscriptKey], used in the +hash256 fragment. Read more
The associated [bitcoin::hashes::ripemd160::Hash] for this [MiniscriptKey] type, used +in the ripemd160 fragment. Read more
The associated [bitcoin::hashes::hash160::Hash] for this [MiniscriptKey] type, used in +the hash160 fragment. Read more
Returns true if the pubkey is uncompressed. Defaults to false.
Returns true if the pubkey is an x-only pubkey. Defaults to false.
Returns the number of different derivation paths in this key. Only >1 for keys +in BIP389 multipath descriptors. 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_wallet/descriptor/enum.Legacy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/enum.Legacy.html new file mode 100644 index 0000000000..06a02a1e8a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/enum.Legacy.html @@ -0,0 +1,54 @@ +Legacy in bdk_wallet::descriptor - Rust
pub enum Legacy {}
Expand description

Legacy ScriptContext +To be used as P2SH scripts +For creation of Bare scriptpubkeys, construct the Miniscript +under Bare 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 <= +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 consensus key associated with the type. Must be a parseable key
Depending on ScriptContext, fragments can be malleable. For Example, +under Legacy context, PkH is malleable because it is possible to +estimate the cost of satisfaction because of compressed keys +This is currently only used in compiler code for removing malleable +compilations. +This does NOT recursively check if the children of the fragment are +valid or not. Since the compilation proceeds in a leaf to root fashion, +a recursive check is unnecessary. Read more
Each context has slightly different rules on what Pks are allowed in descriptors +Legacy/Bare does not allow x_only keys +Segwit does not allow uncompressed keys and x_only keys +Tapscript does not allow uncompressed keys Read more
Check whether the given satisfaction is valid under the ScriptContext +For example, segwit satisfactions may fail if the witness len is more +3600 or number of stack elements are more than 100. Read more
Depending on script Context, some of the Terminals might not +be valid under the current consensus rules. +Or some of the script resource limits may have been exceeded. +These miniscripts would never be accepted by the Bitcoin network and hence +it is safe to discard them +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +uncompressed public keys are non-standard and thus invalid. +In LegacyP2SH context, scripts above 520 bytes are invalid. +Post Tapscript upgrade, this would have to consider other nodes. +This does NOT recursively check the miniscript fragments. Read more
Consensus rules at the Miniscript satisfaction time. +It is possible that some paths of miniscript may exceed resource limits +and our current satisfier and lifting analysis would not work correctly. +For example, satisfaction path(Legacy/Segwitv0) may require more than 201 opcodes. Read more
Policy rules at the Miniscript satisfaction time. +It is possible that some paths of miniscript may exceed resource limits +and our current satisfier and lifting analysis would not work correctly. +For example, satisfaction path in Legacy context scriptSig more +than 1650 bytes Read more
Depending on script context, the size of a satifaction witness may slightly differ.
Get the len of public key when serialized based on context +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
Depending on script Context, some of the script resource limits +may have been exceeded under the current bitcoin core policy rules +These miniscripts would never be accepted by the Bitcoin network and hence +it is safe to discard them. (unless explicitly disabled by non-standard flag) +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +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.

+

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_wallet/descriptor/enum.Segwitv0.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/enum.Segwitv0.html new file mode 100644 index 0000000000..991314fe91 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/enum.Segwitv0.html @@ -0,0 +1,51 @@ +Segwitv0 in bdk_wallet::descriptor - Rust
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 <= +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 consensus key associated with the type. Must be a parseable key
Depending on ScriptContext, fragments can be malleable. For Example, +under Legacy context, PkH is malleable because it is possible to +estimate the cost of satisfaction because of compressed keys +This is currently only used in compiler code for removing malleable +compilations. +This does NOT recursively check if the children of the fragment are +valid or not. Since the compilation proceeds in a leaf to root fashion, +a recursive check is unnecessary. Read more
Each context has slightly different rules on what Pks are allowed in descriptors +Legacy/Bare does not allow x_only keys +Segwit does not allow uncompressed keys and x_only keys +Tapscript does not allow uncompressed keys Read more
Check whether the given satisfaction is valid under the ScriptContext +For example, segwit satisfactions may fail if the witness len is more +3600 or number of stack elements are more than 100. Read more
Depending on script Context, some of the Terminals might not +be valid under the current consensus rules. +Or some of the script resource limits may have been exceeded. +These miniscripts would never be accepted by the Bitcoin network and hence +it is safe to discard them +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +uncompressed public keys are non-standard and thus invalid. +In LegacyP2SH context, scripts above 520 bytes are invalid. +Post Tapscript upgrade, this would have to consider other nodes. +This does NOT recursively check the miniscript fragments. Read more
Consensus rules at the Miniscript satisfaction time. +It is possible that some paths of miniscript may exceed resource limits +and our current satisfier and lifting analysis would not work correctly. +For example, satisfaction path(Legacy/Segwitv0) may require more than 201 opcodes. Read more
Depending on script Context, some of the script resource limits +may have been exceeded under the current bitcoin core policy rules +These miniscripts would never be accepted by the Bitcoin network and hence +it is safe to discard them. (unless explicitly disabled by non-standard flag) +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +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
Policy rules at the Miniscript satisfaction time. +It is possible that some paths of miniscript may exceed resource limits +and our current satisfier and lifting analysis would not work correctly. +For example, satisfaction path in Legacy context scriptSig more +than 1650 bytes Read more
Depending on script context, the size of a satifaction witness may slightly differ.
Get the len of public key when serialized based on context +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.

+

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_wallet/descriptor/error/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/error/enum.Error.html new file mode 100644 index 0000000000..93e85084a6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/error/enum.Error.html @@ -0,0 +1,33 @@ +Error in bdk_wallet::descriptor::error - Rust
pub enum Error {
+    InvalidHdKeyPath,
+    InvalidDescriptorChecksum,
+    HardenedDerivationXpub,
+    MultiPath,
+    Key(KeyError),
+    Policy(PolicyError),
+    InvalidDescriptorCharacter(u8),
+    Bip32(Error),
+    Base58(Error),
+    Pk(Error),
+    Miniscript(Error),
+    Hex(HexToBytesError),
+}
Expand description

Errors related to the parsing and usage of descriptors

+

Variants§

§

InvalidHdKeyPath

Invalid HD Key path, such as having a wildcard but a length != 1

+
§

InvalidDescriptorChecksum

The provided descriptor doesn’t match its checksum

+
§

HardenedDerivationXpub

The descriptor contains hardened derivation steps on public extended keys

+
§

MultiPath

The descriptor contains multipath keys

+
§

Key(KeyError)

Error thrown while working with keys

+
§

Policy(PolicyError)

Error while extracting and manipulating policies

+
§

InvalidDescriptorCharacter(u8)

Invalid byte found in the descriptor checksum

+
§

Bip32(Error)

BIP32 error

+
§

Base58(Error)

Error during base58 decoding

+
§

Pk(Error)

Key-related error

+
§

Miniscript(Error)

Miniscript error

+
§

Hex(HexToBytesError)

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.

+

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/descriptor/error/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/error/index.html new file mode 100644 index 0000000000..d8f68540f9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/error/index.html @@ -0,0 +1,3 @@ +bdk_wallet::descriptor::error - Rust

Module bdk_wallet::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_wallet/descriptor/error/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/error/sidebar-items.js new file mode 100644 index 0000000000..eb47e2c4d1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/error/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["Error","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_wallet/descriptor/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/index.html new file mode 100644 index 0000000000..5ac9398405 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/index.html @@ -0,0 +1,13 @@ +bdk_wallet::descriptor - Rust

Module bdk_wallet::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

The top-level miniscript abstract syntax tree (AST).

Enums

Script descriptor
The descriptor pubkey, either a single pubkey or an xpub.
Legacy ScriptContext +To be used as P2SH scripts +For creation of Bare scriptpubkeys, construct the Miniscript +under Bare ScriptContext
Segwitv0 ScriptContext

Traits

Trait implemented on Descriptors to add a method to extract the spending policy
Trait for types which can be converted into an ExtendedDescriptor and a KeyMap usable by a wallet in a specific [Network]
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 Definitions

Alias for a Descriptor that contains extended derived keys
Alias for a Descriptor that can contain extended keys using DescriptorPublicKey
Alias for the type of maps that represent derivation paths in a psbt::Input or +psbt::Output
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_wallet/descriptor/policy/enum.BuildSatisfaction.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.BuildSatisfaction.html new file mode 100644 index 0000000000..f55adcce65 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.BuildSatisfaction.html @@ -0,0 +1,22 @@ +BuildSatisfaction in bdk_wallet::descriptor::policy - Rust
pub enum BuildSatisfaction<'a> {
+    None,
+    Psbt(&'a Psbt),
+    PsbtTimelocks {
+        psbt: &'a Psbt,
+        current_height: u32,
+        input_max_height: u32,
+    },
+}
Expand description

Options to build the satisfaction field in the policy

+

Variants§

§

None

Don’t generate satisfaction field

+
§

Psbt(&'a Psbt)

Analyze the given PSBT to check for existing signatures

+
§

PsbtTimelocks

Fields

§psbt: &'a Psbt

Given PSBT

+
§current_height: u32

Current blockchain height

+
§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.

+

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_wallet/descriptor/policy/enum.PkOrF.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.PkOrF.html new file mode 100644 index 0000000000..9a672c46df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.PkOrF.html @@ -0,0 +1,16 @@ +PkOrF in bdk_wallet::descriptor::policy - Rust
pub enum PkOrF {
+    Pubkey(PublicKey),
+    XOnlyPubkey(XOnlyPublicKey),
+    Fingerprint(Fingerprint),
+}
Expand description

A unique identifier for a key

+

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 +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_wallet/descriptor/policy/enum.PolicyError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.PolicyError.html new file mode 100644 index 0000000000..00fc3d1f11 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.PolicyError.html @@ -0,0 +1,23 @@ +PolicyError in bdk_wallet::descriptor::policy - Rust
pub enum PolicyError {
+    NotEnoughItemsSelected(String),
+    IndexOutOfRange(usize),
+    AddOnLeaf,
+    AddOnPartialComplete,
+    MixedTimelockUnits,
+    IncompatibleConditions,
+}
Expand description

Errors that can happen while extracting and manipulating policies

+

Variants§

§

NotEnoughItemsSelected(String)

Not enough items are selected to satisfy a SatisfiableItem::Thresh or a SatisfiableItem::Multisig

+
§

IndexOutOfRange(usize)

Index out of range for an item to satisfy a SatisfiableItem::Thresh or a SatisfiableItem::Multisig

+
§

AddOnLeaf

Can not add to an item that is Satisfaction::None or Satisfaction::Complete

+
§

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 +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
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/descriptor/policy/enum.Satisfaction.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.Satisfaction.html new file mode 100644 index 0000000000..5e64987c32 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.Satisfaction.html @@ -0,0 +1,44 @@ +Satisfaction in bdk_wallet::descriptor::policy - Rust
pub enum Satisfaction {
+    Partial {
+        n: usize,
+        m: usize,
+        items: Vec<usize>,
+        sorted: Option<bool>,
+        conditions: ConditionMap,
+    },
+    PartialComplete {
+        n: usize,
+        m: usize,
+        items: Vec<usize>,
+        sorted: Option<bool>,
+        conditions: FoldedConditionMap,
+    },
+    Complete {
+        condition: Condition,
+    },
+    None,
+}
Expand description

Represent if and how much a policy item is satisfied by the wallet’s descriptor

+

Variants§

§

Partial

Fields

§n: usize

Total number of items

+
§m: usize

Threshold

+
§items: Vec<usize>

The items that can be satisfied by the descriptor or are satisfied in the PSBT

+
§sorted: Option<bool>

Whether the items are sorted in lexicographic order (used by sortedmulti)

+
§conditions: ConditionMap

Extra conditions that also need to be satisfied

+

Only a partial satisfaction of some kind of threshold policy

+
§

PartialComplete

Fields

§n: usize

Total number of items

+
§m: usize

Threshold

+
§items: Vec<usize>

The items that can be satisfied by the descriptor

+
§sorted: Option<bool>

Whether the items are sorted in lexicographic order (used by sortedmulti)

+
§conditions: FoldedConditionMap

Extra conditions that also need to be satisfied

+

Can reach the threshold of some kind of threshold policy

+
§

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 +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_wallet/descriptor/policy/enum.SatisfiableItem.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.SatisfiableItem.html new file mode 100644 index 0000000000..19645b79ba --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/enum.SatisfiableItem.html @@ -0,0 +1,60 @@ +SatisfiableItem in bdk_wallet::descriptor::policy - Rust
pub enum SatisfiableItem {
+    EcdsaSignature(PkOrF),
+    SchnorrSignature(PkOrF),
+    Sha256Preimage {
+        hash: Hash,
+    },
+    Hash256Preimage {
+        hash: Hash,
+    },
+    Ripemd160Preimage {
+        hash: Hash,
+    },
+    Hash160Preimage {
+        hash: Hash,
+    },
+    AbsoluteTimelock {
+        value: LockTime,
+    },
+    RelativeTimelock {
+        value: Sequence,
+    },
+    Multisig {
+        keys: Vec<PkOrF>,
+        threshold: usize,
+    },
+    Thresh {
+        items: Vec<Policy>,
+        threshold: usize,
+    },
+}
Expand description

An item that needs to be satisfied

+

Variants§

§

EcdsaSignature(PkOrF)

ECDSA Signature for a raw public key

+
§

SchnorrSignature(PkOrF)

Schnorr Signature for a raw public key

+
§

Sha256Preimage

Fields

§hash: Hash

The digest value

+

SHA256 preimage hash

+
§

Hash256Preimage

Fields

§hash: Hash

The digest value

+

Double SHA256 preimage hash

+
§

Ripemd160Preimage

Fields

§hash: Hash

The digest value

+

RIPEMD160 preimage hash

+
§

Hash160Preimage

Fields

§hash: Hash

The digest value

+

SHA256 then RIPEMD160 preimage hash

+
§

AbsoluteTimelock

Fields

§value: LockTime

The timelock value

+

Absolute timeclock timestamp

+
§

RelativeTimelock

Fields

§value: Sequence

The timelock value

+

Relative timelock locktime

+
§

Multisig

Fields

§keys: Vec<PkOrF>

The raw public key or extended key fingerprint

+
§threshold: usize

The required threshold count

+

Multi-signature public keys with threshold count

+
§

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 +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_wallet/descriptor/policy/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/index.html new file mode 100644 index 0000000000..df565ed8d7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/index.html @@ -0,0 +1,18 @@ +bdk_wallet::descriptor::policy - Rust

Module bdk_wallet::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.

+

Example

+
use bdk_wallet::descriptor::policy::BuildSatisfaction;
+let secp = Secp256k1::new();
+let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
+
+let (extended_desc, key_map) = ExtendedDescriptor::parse_descriptor(&secp, desc)?;
+println!("{:?}", extended_desc);
+
+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).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_wallet/descriptor/policy/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/sidebar-items.js new file mode 100644 index 0000000000..0b375ed6fb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["BuildSatisfaction","Options to build the satisfaction field in the policy"],["PkOrF","A unique identifier for a key"],["PolicyError","Errors that can happen while extracting and manipulating policies"],["Satisfaction","Represent if and how much a policy item is satisfied by the wallet’s descriptor"],["SatisfiableItem","An item that needs to be satisfied"]],"struct":[["Condition","An extra condition that must be satisfied but that is out of control of the user TODO: use `bitcoin::LockTime` and `bitcoin::Sequence`"],["Policy","Descriptor spending policy"]],"type":[["ConditionMap","Type for a map of sets of [`Condition`] items keyed by each set’s index"],["FoldedConditionMap","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_wallet/descriptor/policy/struct.Condition.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/struct.Condition.html new file mode 100644 index 0000000000..92587eb153 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/struct.Condition.html @@ -0,0 +1,18 @@ +Condition in bdk_wallet::descriptor::policy - Rust
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 +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_wallet/descriptor/policy/struct.Policy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/struct.Policy.html new file mode 100644 index 0000000000..c98086a865 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/struct.Policy.html @@ -0,0 +1,25 @@ +Policy in bdk_wallet::descriptor::policy - Rust
pub struct Policy {
+    pub id: String,
+    pub item: SatisfiableItem,
+    pub satisfaction: Satisfaction,
+    pub contribution: Satisfaction,
+}
Expand description

Descriptor spending policy

+

Fields§

§id: String

Identifier for this policy node

+
§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 +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 +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 +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_wallet/descriptor/policy/type.ConditionMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/type.ConditionMap.html new file mode 100644 index 0000000000..1c070b4c6d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/type.ConditionMap.html @@ -0,0 +1,3 @@ +ConditionMap in bdk_wallet::descriptor::policy - Rust

Type Definition bdk_wallet::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_wallet/descriptor/policy/type.FoldedConditionMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/type.FoldedConditionMap.html new file mode 100644 index 0000000000..f9199f9602 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/policy/type.FoldedConditionMap.html @@ -0,0 +1,3 @@ +FoldedConditionMap in bdk_wallet::descriptor::policy - Rust
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_wallet/descriptor/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/sidebar-items.js new file mode 100644 index 0000000000..d738efbc83 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["Descriptor","Script descriptor"],["DescriptorPublicKey","The descriptor pubkey, either a single pubkey or an xpub."],["Legacy","Legacy ScriptContext To be used as P2SH scripts For creation of Bare scriptpubkeys, construct the Miniscript under `Bare` ScriptContext"],["Segwitv0","Segwitv0 ScriptContext"]],"mod":[["checksum","Descriptor checksum"],["error","Descriptor errors"],["policy","Descriptor policy"],["template","Descriptor templates"]],"struct":[["Miniscript","The top-level miniscript abstract syntax tree (AST)."]],"trait":[["ExtractPolicy","Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]"],["IntoWalletDescriptor","Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]"],["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":[["DerivedDescriptor","Alias for a [`Descriptor`] that contains extended derived keys"],["ExtendedDescriptor","Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]"],["HdKeyPaths","Alias for the type of maps that represent derivation paths in a `psbt::Input` or `psbt::Output`"],["TapKeyOrigins","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_wallet/descriptor/struct.Miniscript.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/struct.Miniscript.html new file mode 100644 index 0000000000..08eb2bf4f1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/struct.Miniscript.html @@ -0,0 +1,166 @@ +Miniscript in bdk_wallet::descriptor - Rust
pub struct Miniscript<Pk, Ctx>where
    Pk: MiniscriptKey,
    Ctx: ScriptContext,
{ + pub node: Terminal<Pk, Ctx>, + pub ty: Type, + pub ext: ExtData, + /* private fields */ +}
Expand description

The top-level miniscript abstract syntax tree (AST).

+

Fields§

§node: Terminal<Pk, Ctx>

A node in the AST.

+
§ty: Type

The correctness and malleability type information for the AST node.

+
§ext: ExtData

Additional information helpful for extra analysis.

+

Implementations§

Whether all spend paths of miniscript require a signature

+

Whether the miniscript is malleable

+

Whether the miniscript can exceed the resource limits(Opcodes, Stack limit etc)

+

Whether the miniscript contains a combination of timelocks

+

Whether the miniscript has repeated Pk or Pkh

+

Whether the given miniscript contains a raw pkh fragment

+

Check whether the underlying Miniscript is safe under the current context +Lifting these polices would create a semantic representation that does +not represent the underlying semantics when miniscript is spent. +Signing logic may not find satisfaction even if one exists.

+

For most cases, users should be dealing with safe scripts. +Use this function to check whether the guarantees of library hold. +Most functions of the library like would still +work, but results cannot be relied upon

+

Check whether the miniscript follows the given Extra policy [ExtParams]

+

Iterator-related extensions for Miniscript

+

Creates a new [Iter] iterator that will iterate over all Miniscript items within +AST by traversing its branches. For the specific algorithm please see +[Iter::next] function.

+

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 +them.

+

Returns child node with given index, if any

+

Returns Option::Some with cloned n’th public key from the current miniscript item, +if any. Otherwise returns Option::None.

+

NB: The function analyzes only single miniscript item and not any of its descendants in AST.

+

Add type information(Type and Extdata) to Miniscript based on +AstElem fragment. Dependent on display and clone because of Error +Display code of type_check.

+

Create a new Miniscript from a Terminal node and a Type annotation +This does not check the typing rules. The user is responsible for ensuring +that the type provided is correct.

+

You should almost always use Miniscript::from_ast instead of this function.

+

Extracts the AstElem representing the root of the miniscript

+

Get a reference to the inner AstElem representing the root of miniscript

+

Encode as a Bitcoin script

+

Size, in bytes of the script-pubkey. If this Miniscript is used outside +of segwit (e.g. in a bare or P2SH descriptor), this quantity should be +multiplied by 4 to compute the weight.

+

In general, it is not recommended to use this function directly, but +to instead call the corresponding function on a Descriptor, which +will handle the segwit/non-segwit technicalities for you.

+

Maximum number of witness elements used to satisfy the Miniscript +fragment, including the witness script itself. Used to estimate +the weight of the VarInt that specifies this number in a serialized +transaction.

+

This function may returns Error when the Miniscript is +impossible to satisfy

+

Maximum size, in bytes, of a satisfying witness. For Segwit outputs +one_cost should be set to 2, since the number 1 requires two +bytes to encode. For non-segwit outputs one_cost should be set to +1, since OP_1 is available in scriptSigs.

+

In general, it is not recommended to use this function directly, but +to instead call the corresponding function on a Descriptor, which +will handle the segwit/non-segwit technicalities for you.

+

All signatures are assumed to be 73 bytes in size, including the +length prefix (segwit) or push opcode (pre-segwit) and sighash +postfix.

+

Attempt to produce non-malleable satisfying witness for the +witness script represented by the parse tree

+

Attempt to produce a malleable satisfying witness for the +witness script represented by the parse tree

+

Attempt to produce a non-malleable witness template given the assets available

+

Attempt to produce a malleable witness template given the assets available

+

Attempt to parse an insane(scripts don’t clear sanity checks) +script into a Miniscript representation. +Use this to parse scripts with repeated pubkeys, timelock mixing, malleable +scripts without sig or scripts that can exceed resource limits. +Some of the analysis guarantees of miniscript are lost when dealing with +insane scripts. In general, in a multi-party setting users should only +accept sane scripts.

+

Attempt to parse an miniscript with extra features that not yet specified in the spec. +Users should not use this function unless they scripts can/will change in the future. +Currently, this function supports the following features: +- Parsing all insane scripts +- Parsing miniscripts with raw pubkey hashes

+

Allowed extra features can be specified by the ext [ExtParams] argument.

+

Attempt to parse a Script into Miniscript representation.

+

This function will fail parsing for scripts that do not clear the +Miniscript::sanity_check checks. Use Miniscript::parse_insane to +parse such scripts.

+
Decode/Parse a miniscript from script hex
+
use miniscript::{Miniscript, Segwitv0, Tap};
+use miniscript::bitcoin::secp256k1::XOnlyPublicKey;
+use miniscript::bitcoin::hashes::hex::FromHex;
+
+type Segwitv0Script = Miniscript<bitcoin::PublicKey, Segwitv0>;
+type TapScript = Miniscript<XOnlyPublicKey, Tap>;
+
+// parse x-only miniscript in Taproot context
+let tapscript_ms = TapScript::parse(&bitcoin::ScriptBuf::from_hex(
+    "202788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
+).expect("Even length hex"))
+    .expect("Xonly keys are valid only in taproot context");
+// tapscript fails decoding when we use them with compressed keys
+let err = TapScript::parse(&bitcoin::ScriptBuf::from_hex(
+    "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
+).expect("Even length hex"))
+    .expect_err("Compressed keys cannot be used in Taproot context");
+// Segwitv0 succeeds decoding with full keys.
+Segwitv0Script::parse(&bitcoin::ScriptBuf::from_hex(
+    "21022788ee41e76f4f3af603da5bc8fa22997bc0344bb0f95666ba6aaff0242baa99ac",
+).expect("Even length hex"))
+    .expect("Compressed keys are allowed in Segwit context");
+
+

Substitutes raw public keys hashes with the public keys as provided by map.

+

Attempt to parse an insane(scripts don’t clear sanity checks) +from string into a Miniscript representation. +Use this to parse scripts with repeated pubkeys, timelock mixing, malleable +scripts without sig or scripts that can exceed resource limits. +Some of the analysis guarantees of miniscript are lost when dealing with +insane scripts. In general, in a multi-party setting users should only +accept sane scripts.

+

Attempt to parse an Miniscripts that don’t follow the spec. +Use this to parse scripts with repeated pubkeys, timelock mixing, malleable +scripts, raw pubkey hashes without sig or scripts that can exceed resource limits.

+

Use [ExtParams] builder to specify the types of non-sane rules to allow while parsing.

+

Lifting corresponds to conversion of a miniscript into a [Semantic] +policy for human readable or machine analysis. However, naively lifting +miniscripts can result in incorrect interpretations that don’t +correspond to the underlying semantics when we try to spend them on +bitcoin network. This can occur if the miniscript contains:

+
    +
  1. A combination of timelocks
  2. +
  3. A spend that exceeds resource limits
  4. +
+

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 +do not clear the Miniscript::sanity_check checks.

+
The associated error which can be returned from parsing.

Parse an expression tree into a Miniscript. As a general rule, this +should not be called directly; rather go through the descriptor API.

+

Hash of Miniscript must depend only on node and not the type information.

+

The type information and extra properties are implied by the AST.

+
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
Converts this object into an abstract policy.

Ord of Miniscript must depend only on node and not the type information.

+

The type information and extra properties are implied by the AST.

+
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

PartialEq of Miniscript must depend only on node and not the type information.

+

The type information and extra properties are implied by the AST.

+
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

PartialOrd of Miniscript must depend only on node and not the type information.

+

The type information and extra properties are implied 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 +for Pk is provided by [Translator]

+
The associated output type. This must be Self<Q>.
Interpret the node as an abstract node.
Accessor for the number of children this node has.
Accessor for the nth child of the node, if a child with that index exists.
Obtains an iterator of all the nodes rooted at the node, in pre-order.
Obtains a verbose iterator of all the nodes rooted at the DAG, in pre-order. Read more
Obtains an iterator of all the nodes rooted at the DAG, in post order. Read more

Eq of Miniscript must depend only on node and not the type information.

+

The type information and extra properties are implied 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.

+

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/descriptor/template/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/index.html new file mode 100644 index 0000000000..e7a908b0d0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/index.html @@ -0,0 +1,5 @@ +bdk_wallet::descriptor::template - Rust
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}/*)
BIP86 template. Expands to tr(key/86'/{0,1}'/0'/{0,1}/*)
BIP86 public template. Expands to tr(key/{0,1}/*)
P2PKH template. Expands to a descriptor pkh(key)
P2TR template. Expands to a descriptor tr(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_wallet/descriptor/template/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/sidebar-items.js new file mode 100644 index 0000000000..c4c1d6d2c1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":[["Bip44","BIP44 template. Expands to `pkh(key/44'/{0,1}'/0'/{0,1}/*)`"],["Bip44Public","BIP44 public template. Expands to `pkh(key/{0,1}/*)`"],["Bip49","BIP49 template. Expands to `sh(wpkh(key/49'/{0,1}'/0'/{0,1}/*))`"],["Bip49Public","BIP49 public template. Expands to `sh(wpkh(key/{0,1}/*))`"],["Bip84","BIP84 template. Expands to `wpkh(key/84'/{0,1}'/0'/{0,1}/*)`"],["Bip84Public","BIP84 public template. Expands to `wpkh(key/{0,1}/*)`"],["Bip86","BIP86 template. Expands to `tr(key/86'/{0,1}'/0'/{0,1}/*)`"],["Bip86Public","BIP86 public template. Expands to `tr(key/{0,1}/*)`"],["P2Pkh","P2PKH template. Expands to a descriptor `pkh(key)`"],["P2TR","P2TR template. Expands to a descriptor `tr(key)`"],["P2Wpkh","P2WPKH template. Expands to a descriptor `wpkh(key)`"],["P2Wpkh_P2Sh","P2WPKH-P2SH template. Expands to a descriptor `sh(wpkh(key))`"]],"trait":[["DescriptorTemplate","Trait for descriptor templates that can be built into a full descriptor"]],"type":[["DescriptorTemplateOut","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_wallet/descriptor/template/struct.Bip44.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip44.html new file mode 100644 index 0000000000..8bacd77b84 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip44.html @@ -0,0 +1,21 @@ +Bip44 in bdk_wallet::descriptor::template - Rust
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_wallet::template::Bip44;
+
+let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+let mut wallet = Wallet::new_no_persist(
+    Bip44(key.clone(), KeychainKind::External),
+    Some(Bip44(key, KeychainKind::Internal)),
+    Network::Testnet,
+)?;
+
+assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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/descriptor/template/struct.Bip44Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip44Public.html new file mode 100644 index 0000000000..45702cbb2d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip44Public.html @@ -0,0 +1,24 @@ +Bip44Public in bdk_wallet::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 +for the key.

+

Example

+
use bdk_wallet::template::Bip44Public;
+
+let key = bitcoin::bip32::Xpub::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
+let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
+let mut wallet = Wallet::new_no_persist(
+    Bip44Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+)?;
+
+assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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/descriptor/template/struct.Bip49.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip49.html new file mode 100644 index 0000000000..4261eebd55 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip49.html @@ -0,0 +1,21 @@ +Bip49 in bdk_wallet::descriptor::template - Rust
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_wallet::template::Bip49;
+
+let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+let mut wallet = Wallet::new_no_persist(
+    Bip49(key.clone(), KeychainKind::External),
+    Some(Bip49(key, KeychainKind::Internal)),
+    Network::Testnet,
+)?;
+
+assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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/descriptor/template/struct.Bip49Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip49Public.html new file mode 100644 index 0000000000..437675ad1e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip49Public.html @@ -0,0 +1,24 @@ +Bip49Public in bdk_wallet::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 +for the key.

+

Example

+
use bdk_wallet::template::Bip49Public;
+
+let key = bitcoin::bip32::Xpub::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
+let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
+let mut wallet = Wallet::new_no_persist(
+    Bip49Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+)?;
+
+assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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/descriptor/template/struct.Bip84.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip84.html new file mode 100644 index 0000000000..43ec17e0d5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip84.html @@ -0,0 +1,21 @@ +Bip84 in bdk_wallet::descriptor::template - Rust
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_wallet::template::Bip84;
+
+let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+let mut wallet = Wallet::new_no_persist(
+    Bip84(key.clone(), KeychainKind::External),
+    Some(Bip84(key, KeychainKind::Internal)),
+    Network::Testnet,
+)?;
+
+assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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/descriptor/template/struct.Bip84Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip84Public.html new file mode 100644 index 0000000000..1755ec24cf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip84Public.html @@ -0,0 +1,24 @@ +Bip84Public in bdk_wallet::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 +for the key.

+

Example

+
use bdk_wallet::template::Bip84Public;
+
+let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
+let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
+let mut wallet = Wallet::new_no_persist(
+    Bip84Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+)?;
+
+assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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 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/descriptor/template/struct.Bip86.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip86.html new file mode 100644 index 0000000000..ae2306559f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip86.html @@ -0,0 +1,21 @@ +Bip86 in bdk_wallet::descriptor::template - Rust
pub struct Bip86<K: DerivableKey<Tap>>(pub K, pub KeychainKind);
Expand description

BIP86 template. Expands to tr(key/86'/{0,1}'/0'/{0,1}/*)

+

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

+

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

+

Example

+
use bdk_wallet::template::Bip86;
+
+let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+let mut wallet = Wallet::new_no_persist(
+    Bip86(key.clone(), KeychainKind::External),
+    Some(Bip86(key, KeychainKind::Internal)),
+    Network::Testnet,
+)?;
+
+assert_eq!(wallet.next_unused_address(KeychainKind::External)?.to_string(), "tb1p5unlj09djx8xsjwe97269kqtxqpwpu2epeskgqjfk4lnf69v4tnqpp35qu");
+assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDCiHofpEs47kx358bPdJmTZHmCDqQ8qw32upCSxHrSEdeeBs2T5Mq6QMB2ukeMqhNBiyhosBvJErteVhfURPGXPv3qLJPw5MVpHUewsbP2m/0/*)#dkgvr5hm");
+

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 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/descriptor/template/struct.Bip86Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip86Public.html new file mode 100644 index 0000000000..d8793e2c29 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.Bip86Public.html @@ -0,0 +1,24 @@ +Bip86Public in bdk_wallet::descriptor::template - Rust
pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub Fingerprint, pub KeychainKind);
Expand description

BIP86 public template. Expands to tr(key/{0,1}/*)

+

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

+

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

+

See Bip86 for a template that does the full derivation, but requires private data +for the key.

+

Example

+
use bdk_wallet::template::Bip86Public;
+
+let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
+let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
+let mut wallet = Wallet::new_no_persist(
+    Bip86Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(Bip86Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+)?;
+
+assert_eq!(wallet.next_unused_address(KeychainKind::External)?.to_string(), "tb1pwjp9f2k5n0xq73ecuu0c5njvgqr3vkh7yaylmpqvsuuaafymh0msvcmh37");
+assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#2p65srku");
+

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 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/descriptor/template/struct.P2Pkh.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.P2Pkh.html new file mode 100644 index 0000000000..0efccadd31 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.P2Pkh.html @@ -0,0 +1,20 @@ +P2Pkh in bdk_wallet::descriptor::template - Rust
pub struct P2Pkh<K: IntoDescriptorKey<Legacy>>(pub K);
Expand description

P2PKH template. Expands to a descriptor pkh(key)

+

Example

+
use bdk_wallet::template::P2Pkh;
+
+let key =
+    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+let mut wallet = Wallet::new_no_persist(P2Pkh(key), None, Network::Testnet)?;
+
+assert_eq!(
+    wallet
+        .next_unused_address(KeychainKind::External)?
+        .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.

+

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 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/descriptor/template/struct.P2TR.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.P2TR.html new file mode 100644 index 0000000000..8b99dd49b9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.P2TR.html @@ -0,0 +1,20 @@ +P2TR in bdk_wallet::descriptor::template - Rust
pub struct P2TR<K: IntoDescriptorKey<Tap>>(pub K);
Expand description

P2TR template. Expands to a descriptor tr(key)

+

Example

+
use bdk_wallet::template::P2TR;
+
+let key =
+    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+let mut wallet = Wallet::new_no_persist(P2TR(key), None, Network::Testnet)?;
+
+assert_eq!(
+    wallet
+        .next_unused_address(KeychainKind::External)?
+        .to_string(),
+    "tb1pvjf9t34fznr53u5tqhejz4nr69luzkhlvsdsdfq9pglutrpve2xq7hps46"
+);
+

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 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/descriptor/template/struct.P2Wpkh.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.P2Wpkh.html new file mode 100644 index 0000000000..6f3c17fe95 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.P2Wpkh.html @@ -0,0 +1,20 @@ +P2Wpkh in bdk_wallet::descriptor::template - Rust
pub struct P2Wpkh<K: IntoDescriptorKey<Segwitv0>>(pub K);
Expand description

P2WPKH template. Expands to a descriptor wpkh(key)

+

Example

+
use bdk_wallet::template::P2Wpkh;
+
+let key =
+    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+let mut wallet = Wallet::new_no_persist(P2Wpkh(key), None, Network::Testnet)?;
+
+assert_eq!(
+    wallet
+        .next_unused_address(KeychainKind::External)?
+        .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.

+

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 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/descriptor/template/struct.P2Wpkh_P2Sh.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.P2Wpkh_P2Sh.html new file mode 100644 index 0000000000..5bff5e37c5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/struct.P2Wpkh_P2Sh.html @@ -0,0 +1,20 @@ +P2Wpkh_P2Sh in bdk_wallet::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_wallet::template::P2Wpkh_P2Sh;
+
+let key =
+    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+let mut wallet = Wallet::new_no_persist(P2Wpkh_P2Sh(key), None, Network::Testnet)?;
+
+assert_eq!(
+    wallet
+        .next_unused_address(KeychainKind::External)?
+        .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.

+

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 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/descriptor/template/trait.DescriptorTemplate.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/trait.DescriptorTemplate.html new file mode 100644 index 0000000000..8f8a544d2c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/trait.DescriptorTemplate.html @@ -0,0 +1,22 @@ +DescriptorTemplate in bdk_wallet::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 +passed directly to the Wallet constructor.

+

Example

+
use bdk_wallet::descriptor::error::Error as DescriptorError;
+use bdk_wallet::keys::{IntoDescriptorKey, KeyError};
+use bdk_wallet::miniscript::Legacy;
+use bdk_wallet::template::{DescriptorTemplate, DescriptorTemplateOut};
+use bitcoin::Network;
+
+struct MyP2PKH<K: IntoDescriptorKey<Legacy>>(K);
+
+impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        Ok(bdk_wallet::descriptor!(pkh(self.0))?)
+    }
+}
+

Required Methods§

Build the complete descriptor

+

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/type.DescriptorTemplateOut.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/type.DescriptorTemplateOut.html new file mode 100644 index 0000000000..9915817438 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/template/type.DescriptorTemplateOut.html @@ -0,0 +1,3 @@ +DescriptorTemplateOut in bdk_wallet::descriptor::template - Rust
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_wallet/descriptor/trait.ExtractPolicy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/trait.ExtractPolicy.html new file mode 100644 index 0000000000..fbcf99b231 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/trait.ExtractPolicy.html @@ -0,0 +1,6 @@ +ExtractPolicy in bdk_wallet::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 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/trait.IntoWalletDescriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/trait.IntoWalletDescriptor.html new file mode 100644 index 0000000000..e6212f3c85 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/trait.IntoWalletDescriptor.html @@ -0,0 +1,8 @@ +IntoWalletDescriptor in bdk_wallet::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§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/trait.ScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/trait.ScriptContext.html new file mode 100644 index 0000000000..44a4e30442 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/trait.ScriptContext.html @@ -0,0 +1,93 @@ +ScriptContext in bdk_wallet::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 16 methods fn check_terminal_non_malleable<Pk>(
        _frag: &Terminal<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
; + fn check_pk<Pk>(pk: &Pk) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
; + fn max_satisfaction_size<Pk>(ms: &Miniscript<Pk, Self>) -> Option<usize>
    where
        Pk: MiniscriptKey
; + fn sig_type() -> SigType; + fn pk_len<Pk>(pk: &Pk) -> usize
    where
        Pk: MiniscriptKey
; + fn name_str() -> &'static str; + + fn check_witness<Pk>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_global_consensus_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_global_policy_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_local_consensus_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_local_policy_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_global_validity<Pk>(
        ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_local_validity<Pk>(
        ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn top_level_type_check<Pk>(ms: &Miniscript<Pk, Self>) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, + { ... } + fn other_top_level_checks<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, + { ... } + fn top_level_checks<Pk>(ms: &Miniscript<Pk, Self>) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, + { ... } +
}
Expand description

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

+

Required Associated Types§

The consensus key associated with the type. Must be a parseable key

+

Required Methods§

Depending on ScriptContext, fragments can be malleable. For Example, +under Legacy context, PkH is malleable because it is possible to +estimate the cost of satisfaction because of compressed keys +This is currently only used in compiler code for removing malleable +compilations. +This does NOT recursively check if the children of the fragment are +valid or not. Since the compilation proceeds in a leaf to root fashion, +a recursive check is unnecessary.

+

Each context has slightly different rules on what Pks are allowed in descriptors +Legacy/Bare does not allow x_only keys +Segwit does not allow uncompressed keys and x_only keys +Tapscript does not allow uncompressed keys

+

Depending on script context, the size of a satifaction witness may slightly differ.

+

The type of signature required for satisfaction

+

Get the len of public key when serialized based on context +Note that this includes the serialization prefix. Returns +34/66 for Bare/Legacy based on key compressedness +34 for Segwitv0, 33 for Tap

+

Local helper function to display error messages with context

+

Provided Methods§

Check whether the given satisfaction is valid under the ScriptContext +For example, segwit satisfactions may fail if the witness len is more +3600 or number of stack elements are more than 100.

+

Depending on script Context, some of the Terminals might not +be valid under the current consensus rules. +Or some of the script resource limits may have been exceeded. +These miniscripts would never be accepted by the Bitcoin network and hence +it is safe to discard them +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +uncompressed public keys are non-standard and thus invalid. +In LegacyP2SH context, scripts above 520 bytes are invalid. +Post Tapscript upgrade, this would have to consider other nodes. +This does NOT recursively check the miniscript fragments.

+

Depending on script Context, some of the script resource limits +may have been exceeded under the current bitcoin core policy rules +These miniscripts would never be accepted by the Bitcoin network and hence +it is safe to discard them. (unless explicitly disabled by non-standard flag) +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +scripts over 3600 bytes are invalid. +Post Tapscript upgrade, this would have to consider other nodes. +This does NOT recursively check the miniscript fragments.

+

Consensus rules at the Miniscript satisfaction time. +It is possible that some paths of miniscript may exceed resource limits +and our current satisfier and lifting analysis would not work correctly. +For example, satisfaction path(Legacy/Segwitv0) may require more than 201 opcodes.

+

Policy rules at the Miniscript satisfaction time. +It is possible that some paths of miniscript may exceed resource limits +and our current satisfier and lifting analysis would not work correctly. +For example, satisfaction path in Legacy context scriptSig more +than 1650 bytes

+

Check the consensus + policy(if not disabled) rules that are not based +satisfaction

+

Check the consensus + policy(if not disabled) rules including the +ones for satisfaction

+

Check whether the top-level is type B

+

Other top level checks that are context specific

+

Check top level consensus rules.

+

Implementors§

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

Type Definition bdk_wallet::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_wallet/descriptor/type.ExtendedDescriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/type.ExtendedDescriptor.html new file mode 100644 index 0000000000..f6727670c7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/type.ExtendedDescriptor.html @@ -0,0 +1,3 @@ +ExtendedDescriptor in bdk_wallet::descriptor - Rust

Type Definition bdk_wallet::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_wallet/descriptor/type.HdKeyPaths.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/type.HdKeyPaths.html new file mode 100644 index 0000000000..5345eef819 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/type.HdKeyPaths.html @@ -0,0 +1,4 @@ +HdKeyPaths in bdk_wallet::descriptor - Rust

Type Definition bdk_wallet::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_wallet/descriptor/type.TapKeyOrigins.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/type.TapKeyOrigins.html new file mode 100644 index 0000000000..3d92ba21e3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/descriptor/type.TapKeyOrigins.html @@ -0,0 +1,4 @@ +TapKeyOrigins in bdk_wallet::descriptor - Rust

Type Definition bdk_wallet::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_wallet/enum.KeychainKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/enum.KeychainKind.html new file mode 100644 index 0000000000..2930786a68 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/enum.KeychainKind.html @@ -0,0 +1,17 @@ +KeychainKind in bdk_wallet - Rust
pub enum KeychainKind {
+    External,
+    Internal,
+}
Expand description

Types of keychains

+

Variants§

§

External

External keychain, used for deriving recipient addresses.

+
§

Internal

Internal keychain, used for deriving change addresses.

+

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
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_wallet/enum.Utxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/enum.Utxo.html new file mode 100644 index 0000000000..1c846174a8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/enum.Utxo.html @@ -0,0 +1,24 @@ +Utxo in bdk_wallet - Rust

Enum bdk_wallet::Utxo

source ·
pub enum Utxo {
+    Local(LocalOutput),
+    Foreign {
+        outpoint: OutPoint,
+        sequence: Option<Sequence>,
+        psbt_input: Box<Input>,
+    },
+}
Expand description

An unspent transaction output (UTXO).

+

Variants§

§

Local(LocalOutput)

A UTXO owned by the local wallet.

+
§

Foreign

Fields

§outpoint: OutPoint

The location of the output.

+
§sequence: Option<Sequence>

The nSequence value to set for this input.

+
§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

+

Get the sequence number if an explicit sequence number has to be set for this input.

+

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_wallet/fn.version.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/fn.version.html new file mode 100644 index 0000000000..7c677a3767 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/fn.version.html @@ -0,0 +1,3 @@ +version in bdk_wallet - Rust

Function bdk_wallet::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_wallet/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/index.html new file mode 100644 index 0000000000..efc19fbdaa --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/index.html @@ -0,0 +1,170 @@ +bdk_wallet - Rust

Crate bdk_wallet

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.63.0+ + Chat on Discord +

+

+ Project Homepage + | + Documentation +

+
+

BDK Wallet

+

The bdk_wallet 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 details about the API of Wallet see the module-level documentation.

+

Blockchain data

+

In order to get blockchain data for Wallet to consume, you should configure a client from +an available chain source. Typically you make a request to the chain source and get a response +that the Wallet can use to update its view of the chain.

+

Blockchain Data Sources

+
    +
  • bdk_esplora: Grabs blockchain data from Esplora for updating BDK structures.
  • +
  • bdk_electrum: Grabs blockchain data from Electrum for updating BDK structures.
  • +
  • bdk_bitcoind_rpc: Grabs blockchain data from Bitcoin Core for updating BDK structures.
  • +
+

Examples

+ +

Persistence

+

To persist the Wallet on disk, it must be constructed with a PersistBackend implementation.

+

Implementations

+ +

Example

+ + +
ⓘ
use bdk_wallet::{bitcoin::Network, wallet::{ChangeSet, Wallet}};
+
+fn main() {
+    // Create a new file `Store`.
+    let db = bdk_file_store::Store::<ChangeSet>::open_or_create_new(b"magic_bytes", "path/to/my_wallet.db").expect("create store");
+
+    let descriptor = "wpkh(tprv8ZgxMBicQKsPdcAqYBpzAFwU5yxBUo88ggoBqu1qPcHUfSbKK1sKMLmC7EAk438btHQrSdu3jGGQa6PA71nvH5nkDexhLteJqkM4dQmWF9g/84'/1'/0'/0/*)";
+    let mut wallet = Wallet::new_or_load(descriptor, None, db, Network::Testnet).expect("create or load wallet");
+
+    // Insert a single `TxOut` at `OutPoint` into the wallet.
+    let _ = wallet.insert_txout(outpoint, txout);
+    wallet.commit().expect("must write to database");
+}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Testing

Unit testing

cargo test
+

License

+

Licensed under either of

+ +

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 Psbt structure.
Wallet

Macros

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

Structs

An unspent output owned by a Wallet.
A Utxo with its satisfaction_weight.

Enums

Types of keychains
An unspent transaction output (UTXO).

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_wallet/keys/enum.DescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.DescriptorKey.html new file mode 100644 index 0000000000..2aecf98554 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.DescriptorKey.html @@ -0,0 +1,13 @@ +DescriptorKey in bdk_wallet::keys - Rust
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_wallet::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 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/keys/enum.DescriptorPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.DescriptorPublicKey.html new file mode 100644 index 0000000000..f546bc0dc0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.DescriptorPublicKey.html @@ -0,0 +1,55 @@ +DescriptorPublicKey in bdk_wallet::keys - Rust
pub enum DescriptorPublicKey {
+    Single(SinglePub),
+    XPub(DescriptorXKey<Xpub>),
+    MultiXPub(DescriptorMultiXKey<Xpub>),
+}
Expand description

The descriptor pubkey, either a single pubkey or an xpub.

+

Variants§

§

Single(SinglePub)

Single public key.

+
§

XPub(DescriptorXKey<Xpub>)

Extended public key (xpub).

+
§

MultiXPub(DescriptorMultiXKey<Xpub>)

Multiple extended public keys.

+

Implementations§

The fingerprint of the master key associated with this key, 0x00000000 if none.

+

Full path, from the master key

+

For wildcard keys this will return the path up to the wildcard, so you +can get full paths by appending one additional derivation step, according +to the wildcard type (hardened or normal).

+

For multipath extended keys, this returns None.

+

Returns a vector containing the full derivation paths from the master key. +The vector will contain just one element for single keys, and multiple elements +for multipath extended keys.

+

For wildcard keys this will return the path up to the wildcard, so you +can get full paths by appending one additional derivation step, according +to the wildcard type (hardened or normal).

+
👎Deprecated: use has_wildcard instead

Whether or not the key has a wildcard

+

Whether or not the key has a wildcard

+
👎Deprecated: use at_derivation_index instead

Deprecated name for Self::at_derivation_index.

+

Replaces any wildcard (i.e. /*) in the key with a particular derivation index, turning it into a +definite key (i.e. one where all the derivation paths are set).

+
Returns
+
    +
  • If this key is not an xpub, returns self.
  • +
  • If this key is an xpub but does not have a wildcard, returns self.
  • +
  • Otherwise, returns the xpub at derivation index (removing the wildcard).
  • +
+
Errors
+
    +
  • If index is hardened.
  • +
+

Whether or not this key has multiple derivation paths.

+

Get as many keys as derivation paths in this key.

+

For raw public key and single-path extended keys it will return the key itself. +For multipath extended keys it will return a single-path extended key per derivation +path.

+

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
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
Convert self into a Assets struct
Turn the key into a DescriptorKey within the requested ScriptContext
The associated [bitcoin::hashes::sha256::Hash] for this [MiniscriptKey], used in the +sha256 fragment. Read more
The associated [miniscript::hash256::Hash] for this [MiniscriptKey], used in the +hash256 fragment. Read more
The associated [bitcoin::hashes::ripemd160::Hash] for this [MiniscriptKey] type, used +in the ripemd160 fragment. Read more
The associated [bitcoin::hashes::hash160::Hash] for this [MiniscriptKey] type, used in +the hash160 fragment. Read more
Returns true if the pubkey is uncompressed. Defaults to false.
Returns true if the pubkey is an x-only pubkey. Defaults to false.
Returns the number of different derivation paths in this key. Only >1 for keys +in BIP389 multipath descriptors. 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_wallet/keys/enum.DescriptorSecretKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.DescriptorSecretKey.html new file mode 100644 index 0000000000..46495d3cc0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.DescriptorSecretKey.html @@ -0,0 +1,27 @@ +DescriptorSecretKey in bdk_wallet::keys - Rust
pub enum DescriptorSecretKey {
+    Single(SinglePriv),
+    XPrv(DescriptorXKey<Xpriv>),
+    MultiXPrv(DescriptorMultiXKey<Xpriv>),
+}
Expand description

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

+

Variants§

§

Single(SinglePriv)

Single private key.

+
§

XPrv(DescriptorXKey<Xpriv>)

Extended private key (xpriv).

+
§

MultiXPrv(DescriptorMultiXKey<Xpriv>)

Multiple extended private keys.

+

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.

+

It will return an error if the key is a “multi-xpriv”, as we wouldn’t +always be able to apply hardened derivation steps if there are multiple +paths.

+

Whether or not this key has multiple derivation paths.

+

Get as many keys as derivation paths in this key.

+

For raw keys and single-path extended keys it will return the key itself. +For multipath extended keys it will return a single-path extended key per derivation +path.

+

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 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
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_wallet/keys/enum.ExtendedKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.ExtendedKey.html new file mode 100644 index 0000000000..d19b1dc125 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.ExtendedKey.html @@ -0,0 +1,22 @@ +ExtendedKey in bdk_wallet::keys - Rust
pub enum ExtendedKey<Ctx: ScriptContext = Legacy> {
+    Private((Xpriv, PhantomData<Ctx>)),
+    Public((Xpub, PhantomData<Ctx>)),
+}
Expand description

Enum for extended keys that can be either xprv or xpub

+

An instance of ExtendedKey can be constructed from an Xpriv +or an Xpub by using the From trait.

+

Defaults to the Legacy context.

+

Variants§

§

Private((Xpriv, PhantomData<Ctx>))

A private extended key, aka an xprv

+
§

Public((Xpub, 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 Xpriv for the +given [Network], if the key contains the private data

+

Transform the ExtendedKey into an Xpub for the +given [Network]

+

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 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/keys/enum.KeyError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.KeyError.html new file mode 100644 index 0000000000..42063f2ab6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.KeyError.html @@ -0,0 +1,21 @@ +KeyError in bdk_wallet::keys - Rust

Enum bdk_wallet::keys::KeyError

source ·
pub enum KeyError {
+    InvalidScriptContext,
+    InvalidNetwork,
+    InvalidChecksum,
+    Message(String),
+    Bip32(Error),
+    Miniscript(Error),
+}
Expand description

Errors thrown while working with keys

+

Variants§

§

InvalidScriptContext

The key cannot exist in the given script context

+
§

InvalidNetwork

The key is not valid for the given network

+
§

InvalidChecksum

The key has an invalid checksum

+
§

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.

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/keys/enum.ScriptContextEnum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.ScriptContextEnum.html new file mode 100644 index 0000000000..b7da1e6400 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.ScriptContextEnum.html @@ -0,0 +1,19 @@ +ScriptContextEnum in bdk_wallet::keys - Rust
pub enum ScriptContextEnum {
+    Legacy,
+    Segwitv0,
+    Tap,
+}
Expand description

Enum representation of the known valid ScriptContexts

+

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 +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_wallet/keys/enum.SinglePubKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.SinglePubKey.html new file mode 100644 index 0000000000..3adeb1e48b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/enum.SinglePubKey.html @@ -0,0 +1,16 @@ +SinglePubKey in bdk_wallet::keys - Rust
pub enum SinglePubKey {
+    FullKey(PublicKey),
+    XOnly(XOnlyPublicKey),
+}
Expand description

Single public key without any origin or range information.

+

Variants§

§

FullKey(PublicKey)

A bitcoin public key (compressed or uncompressed).

+
§

XOnly(XOnlyPublicKey)

An xonly public 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
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
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/keys/fn.any_network.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/fn.any_network.html new file mode 100644 index 0000000000..0849cab6f0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/fn.any_network.html @@ -0,0 +1,3 @@ +any_network in bdk_wallet::keys - Rust

Function bdk_wallet::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_wallet/keys/fn.mainnet_network.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/fn.mainnet_network.html new file mode 100644 index 0000000000..df0122942f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/fn.mainnet_network.html @@ -0,0 +1,3 @@ +mainnet_network in bdk_wallet::keys - Rust

Function bdk_wallet::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_wallet/keys/fn.merge_networks.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/fn.merge_networks.html new file mode 100644 index 0000000000..a31601f1e5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/fn.merge_networks.html @@ -0,0 +1,3 @@ +merge_networks in bdk_wallet::keys - Rust

Function bdk_wallet::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_wallet/keys/fn.test_networks.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/fn.test_networks.html new file mode 100644 index 0000000000..f8aa3f4f0e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/fn.test_networks.html @@ -0,0 +1,3 @@ +test_networks in bdk_wallet::keys - Rust

Function bdk_wallet::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_wallet/keys/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/index.html new file mode 100644 index 0000000000..e0507a585d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/index.html @@ -0,0 +1,6 @@ +bdk_wallet::keys - Rust

Module bdk_wallet::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_wallet/keys/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/sidebar-items.js new file mode 100644 index 0000000000..bb1823d1c3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/sidebar-items.js @@ -0,0 +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"]],"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_wallet/keys/struct.GeneratedKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.GeneratedKey.html new file mode 100644 index 0000000000..86ab913819 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.GeneratedKey.html @@ -0,0 +1,9 @@ +GeneratedKey in bdk_wallet::keys - Rust

Struct bdk_wallet::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 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/keys/struct.PrivateKeyGenerateOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.PrivateKeyGenerateOptions.html new file mode 100644 index 0000000000..f16d95a6a2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.PrivateKeyGenerateOptions.html @@ -0,0 +1,11 @@ +PrivateKeyGenerateOptions in bdk_wallet::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.

+

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_wallet/keys/struct.SinglePriv.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.SinglePriv.html new file mode 100644 index 0000000000..1cec13530c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.SinglePriv.html @@ -0,0 +1,14 @@ +SinglePriv in bdk_wallet::keys - Rust

Struct bdk_wallet::keys::SinglePriv

pub struct SinglePriv {
+    pub origin: Option<(Fingerprint, DerivationPath)>,
+    pub key: PrivateKey,
+}
Expand description

A descriptor [bitcoin::PrivateKey] with optional origin information.

+

Fields§

§origin: Option<(Fingerprint, DerivationPath)>

Origin information (fingerprint and derivation path).

+
§key: PrivateKey

The private 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
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_wallet/keys/struct.SinglePub.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.SinglePub.html new file mode 100644 index 0000000000..0ef63439cd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.SinglePub.html @@ -0,0 +1,16 @@ +SinglePub in bdk_wallet::keys - Rust

Struct bdk_wallet::keys::SinglePub

pub struct SinglePub {
+    pub origin: Option<(Fingerprint, DerivationPath)>,
+    pub key: SinglePubKey,
+}
Expand description

A descriptor SinglePubKey with optional origin information.

+

Fields§

§origin: Option<(Fingerprint, DerivationPath)>

Origin information (fingerprint and derivation path).

+
§key: SinglePubKey

The public 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
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
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/keys/struct.SortedMultiVec.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.SortedMultiVec.html new file mode 100644 index 0000000000..ed303ea30b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/struct.SortedMultiVec.html @@ -0,0 +1,51 @@ +SortedMultiVec in bdk_wallet::keys - Rust
pub struct SortedMultiVec<Pk, Ctx>where
    Pk: MiniscriptKey,
    Ctx: ScriptContext,
{ + pub k: usize, + pub pks: Vec<Pk, Global>, + /* private fields */ +}
Expand description

Contents of a “sortedmulti” descriptor

+

Fields§

§k: usize

signatures required

+
§pks: Vec<Pk, Global>

public keys inside sorted Multi

+

Implementations§

Create a new instance of SortedMultiVec given a list of keys and the threshold

+

Internally checks all the applicable size limits and pubkey types limitations according to the current Ctx.

+

Parse an expression tree into a SortedMultiVec

+

This will panic if fpk returns an uncompressed key when +converting to a Segwit descriptor. To prevent this panic, ensure +fpk returns an error in this case instead.

+

utility function to sanity a sorted multi vec

+

Create Terminal::Multi containing sorted pubkeys

+

Encode as a Bitcoin script

+

Attempt to produce a satisfying witness for the +witness script represented by the parse tree

+

Attempt to produce a witness template given the assets available

+

Size, in bytes of the script-pubkey. If this Miniscript is used outside +of segwit (e.g. in a bare or P2SH descriptor), this quantity should be +multiplied by 4 to compute the weight.

+

In general, it is not recommended to use this function directly, but +to instead call the corresponding function on a Descriptor, which +will handle the segwit/non-segwit technicalities for you.

+

Maximum number of witness elements used to satisfy the Miniscript +fragment, including the witness script itself. Used to estimate +the weight of the VarInt that specifies this number in a serialized +transaction.

+

This function may panic on malformed Miniscript objects which do +not correspond to semantically sane Scripts. (Such scripts should be +rejected at parse time. Any exceptions are bugs.)

+

Maximum size, in bytes, of a satisfying witness. +In general, it is not recommended to use this function directly, but +to instead call the corresponding function on a Descriptor, which +will handle the segwit/non-segwit technicalities for you.

+

All signatures are assumed to be 73 bytes in size, including the +length prefix (segwit) or push opcode (pre-segwit) and sighash +postfix.

+

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
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
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
Converts this 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

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/keys/trait.DerivableKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.DerivableKey.html new file mode 100644 index 0000000000..abbbadd0a5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.DerivableKey.html @@ -0,0 +1,88 @@ +DerivableKey in bdk_wallet::keys - Rust
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> { ... } +}
Expand description

Trait for keys that can be derived.

+

When extra metadata are provided, a DerivableKey can be transformed into a +DescriptorKey: the trait IntoDescriptorKey is automatically implemented +for (DerivableKey, DerivationPath) and +(DerivableKey, KeySource, DerivationPath) tuples.

+

For key types that don’t encode any indication about the path to use (like bip39), it’s +generally recommended to implement this trait instead of IntoDescriptorKey. The same +rules regarding script context and valid networks apply.

+

Examples

+

Key types that can be directly converted into an Xpriv or +an Xpub can implement only the required into_extended_key() method.

+ +
use bdk_wallet::bitcoin;
+use bdk_wallet::bitcoin::bip32;
+use bdk_wallet::keys::{DerivableKey, ExtendedKey, KeyError, ScriptContext};
+
+struct MyCustomKeyType {
+    key_data: bitcoin::PrivateKey,
+    chain_code: [u8; 32],
+    network: bitcoin::Network,
+}
+
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        let xprv = bip32::Xpriv {
+            network: self.network,
+            depth: 0,
+            parent_fingerprint: bip32::Fingerprint::default(),
+            private_key: self.key_data.inner,
+            chain_code: bip32::ChainCode::from(&self.chain_code),
+            child_number: bip32::ChildNumber::Normal { index: 0 },
+        };
+
+        xprv.into_extended_key()
+    }
+}
+

Types that don’t internally encode the [Network] in which they are valid need some extra +steps to override the set of valid networks, otherwise only the network specified in the +Xpriv or Xpub will be considered valid.

+ +
use bdk_wallet::bitcoin;
+use bdk_wallet::bitcoin::bip32;
+use bdk_wallet::keys::{
+    any_network, DerivableKey, DescriptorKey, ExtendedKey, KeyError, ScriptContext,
+};
+
+struct MyCustomKeyType {
+    key_data: bitcoin::PrivateKey,
+    chain_code: [u8; 32],
+}
+
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        let xprv = bip32::Xpriv {
+            network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
+            depth: 0,
+            parent_fingerprint: bip32::Fingerprint::default(),
+            private_key: self.key_data.inner,
+            chain_code: bip32::ChainCode::from(&self.chain_code),
+            child_number: bip32::ChildNumber::Normal { index: 0 },
+        };
+
+        xprv.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)?;
+
+        // Override the set of valid networks here
+        Ok(descriptor_key.override_valid_networks(any_network()))
+    }
+}
+

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 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.ExtScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.ExtScriptContext.html new file mode 100644 index 0000000000..e814a76f88 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.ExtScriptContext.html @@ -0,0 +1,13 @@ +ExtScriptContext in bdk_wallet::keys - Rust
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 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.GeneratableDefaultOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.GeneratableDefaultOptions.html new file mode 100644 index 0000000000..9a185571ee --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.GeneratableDefaultOptions.html @@ -0,0 +1,11 @@ +GeneratableDefaultOptions in bdk_wallet::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 +Options implements Default

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.GeneratableKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.GeneratableKey.html new file mode 100644 index 0000000000..b7e9136391 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.GeneratableKey.html @@ -0,0 +1,21 @@ +GeneratableKey in bdk_wallet::keys - Rust
pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
+    type Entropy: AsMut<[u8]> + Default;
+    type Options;
+    type Error: Debug;
+
+    fn generate_with_entropy(
        options: Self::Options,
        entropy: Self::Entropy
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>; + + fn generate(
        options: Self::Options
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } +}
Expand description

Trait for keys that can be generated

+

The same rules about ScriptContext and ValidNetworks from IntoDescriptorKey apply.

+

This trait is particularly useful when combined with DerivableKey: if Self +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 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.IntoDescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.IntoDescriptorKey.html new file mode 100644 index 0000000000..be0915cf9d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.IntoDescriptorKey.html @@ -0,0 +1,108 @@ +IntoDescriptorKey in bdk_wallet::keys - Rust
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 +formats, like the mnemonics used by Electrum wallets, encode internally whether the wallet is +legacy or segwit. Thus, trying to turn a valid legacy mnemonic into a DescriptorKey +that would become part of a segwit descriptor should fail.

+

For key types that do care about this, the ExtScriptContext trait provides some useful +methods that can be used to check at runtime which Ctx is being used.

+

For key types that can do this check statically (because they can only work within a +single Ctx), the “specialized” trait can be implemented to make the compiler handle the type +checking.

+

Keys also have control over the networks they support: constructing the return object with +DescriptorKey::from_public or DescriptorKey::from_secret allows to specify a set of +ValidNetworks.

+

Examples

+

Key type valid in any context:

+ +
use bdk_wallet::bitcoin::PublicKey;
+
+use bdk_wallet::keys::{DescriptorKey, IntoDescriptorKey, KeyError, ScriptContext};
+
+pub struct MyKeyType {
+    pubkey: PublicKey,
+}
+
+impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for MyKeyType {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        self.pubkey.into_descriptor_key()
+    }
+}
+

Key type that is only valid on mainnet:

+ +
use bdk_wallet::bitcoin::PublicKey;
+
+use bdk_wallet::keys::{
+    mainnet_network, DescriptorKey, DescriptorPublicKey, IntoDescriptorKey, KeyError,
+    ScriptContext, SinglePub, SinglePubKey,
+};
+
+pub struct MyKeyType {
+    pubkey: PublicKey,
+}
+
+impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for MyKeyType {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        Ok(DescriptorKey::from_public(
+            DescriptorPublicKey::Single(SinglePub {
+                origin: None,
+                key: SinglePubKey::FullKey(self.pubkey),
+            }),
+            mainnet_network(),
+        ))
+    }
+}
+

Key type that internally encodes in which context it’s valid. The context is checked at runtime:

+ +
use bdk_wallet::bitcoin::PublicKey;
+
+use bdk_wallet::keys::{
+    DescriptorKey, ExtScriptContext, IntoDescriptorKey, KeyError, ScriptContext,
+};
+
+pub struct MyKeyType {
+    is_legacy: bool,
+    pubkey: PublicKey,
+}
+
+impl<Ctx: ScriptContext + 'static> IntoDescriptorKey<Ctx> for MyKeyType {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        if Ctx::is_legacy() == self.is_legacy {
+            self.pubkey.into_descriptor_key()
+        } else {
+            Err(KeyError::InvalidScriptContext)
+        }
+    }
+}
+

Key type that can only work within miniscript::Segwitv0 context. Only the specialized version +of the trait is implemented.

+

This example deliberately fails to compile, to demonstrate how the compiler can catch when keys +are misused. In this case, the “segwit-only” key is used to build a pkh() descriptor, which +makes the compiler (correctly) fail.

+ +
ⓘ
use bdk_wallet::bitcoin::PublicKey;
+use core::str::FromStr;
+
+use bdk_wallet::keys::{DescriptorKey, IntoDescriptorKey, KeyError};
+
+pub struct MySegwitOnlyKeyType {
+    pubkey: PublicKey,
+}
+
+impl IntoDescriptorKey<bdk_wallet::miniscript::Segwitv0> for MySegwitOnlyKeyType {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<bdk_wallet::miniscript::Segwitv0>, KeyError> {
+        self.pubkey.into_descriptor_key()
+    }
+}
+
+let key = MySegwitOnlyKeyType {
+    pubkey: PublicKey::from_str("...")?,
+};
+let (descriptor, _, _) = bdk_wallet::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_wallet::fragments

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.ScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.ScriptContext.html new file mode 100644 index 0000000000..9cbcf31dcf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/trait.ScriptContext.html @@ -0,0 +1,93 @@ +ScriptContext in bdk_wallet::keys - 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 16 methods fn check_terminal_non_malleable<Pk>(
        _frag: &Terminal<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
; + fn check_pk<Pk>(pk: &Pk) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
; + fn max_satisfaction_size<Pk>(ms: &Miniscript<Pk, Self>) -> Option<usize>
    where
        Pk: MiniscriptKey
; + fn sig_type() -> SigType; + fn pk_len<Pk>(pk: &Pk) -> usize
    where
        Pk: MiniscriptKey
; + fn name_str() -> &'static str; + + fn check_witness<Pk>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_global_consensus_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_global_policy_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_local_consensus_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_local_policy_validity<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_global_validity<Pk>(
        ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn check_local_validity<Pk>(
        ms: &Miniscript<Pk, Self>
    ) -> Result<(), ScriptContextError>
    where
        Pk: MiniscriptKey
, + { ... } + fn top_level_type_check<Pk>(ms: &Miniscript<Pk, Self>) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, + { ... } + fn other_top_level_checks<Pk>(
        _ms: &Miniscript<Pk, Self>
    ) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, + { ... } + fn top_level_checks<Pk>(ms: &Miniscript<Pk, Self>) -> Result<(), Error>
    where
        Pk: MiniscriptKey
, + { ... } +
}
Expand description

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

+

Required Associated Types§

The consensus key associated with the type. Must be a parseable key

+

Required Methods§

Depending on ScriptContext, fragments can be malleable. For Example, +under Legacy context, PkH is malleable because it is possible to +estimate the cost of satisfaction because of compressed keys +This is currently only used in compiler code for removing malleable +compilations. +This does NOT recursively check if the children of the fragment are +valid or not. Since the compilation proceeds in a leaf to root fashion, +a recursive check is unnecessary.

+

Each context has slightly different rules on what Pks are allowed in descriptors +Legacy/Bare does not allow x_only keys +Segwit does not allow uncompressed keys and x_only keys +Tapscript does not allow uncompressed keys

+

Depending on script context, the size of a satifaction witness may slightly differ.

+

The type of signature required for satisfaction

+

Get the len of public key when serialized based on context +Note that this includes the serialization prefix. Returns +34/66 for Bare/Legacy based on key compressedness +34 for Segwitv0, 33 for Tap

+

Local helper function to display error messages with context

+

Provided Methods§

Check whether the given satisfaction is valid under the ScriptContext +For example, segwit satisfactions may fail if the witness len is more +3600 or number of stack elements are more than 100.

+

Depending on script Context, some of the Terminals might not +be valid under the current consensus rules. +Or some of the script resource limits may have been exceeded. +These miniscripts would never be accepted by the Bitcoin network and hence +it is safe to discard them +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +uncompressed public keys are non-standard and thus invalid. +In LegacyP2SH context, scripts above 520 bytes are invalid. +Post Tapscript upgrade, this would have to consider other nodes. +This does NOT recursively check the miniscript fragments.

+

Depending on script Context, some of the script resource limits +may have been exceeded under the current bitcoin core policy rules +These miniscripts would never be accepted by the Bitcoin network and hence +it is safe to discard them. (unless explicitly disabled by non-standard flag) +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +scripts over 3600 bytes are invalid. +Post Tapscript upgrade, this would have to consider other nodes. +This does NOT recursively check the miniscript fragments.

+

Consensus rules at the Miniscript satisfaction time. +It is possible that some paths of miniscript may exceed resource limits +and our current satisfier and lifting analysis would not work correctly. +For example, satisfaction path(Legacy/Segwitv0) may require more than 201 opcodes.

+

Policy rules at the Miniscript satisfaction time. +It is possible that some paths of miniscript may exceed resource limits +and our current satisfier and lifting analysis would not work correctly. +For example, satisfaction path in Legacy context scriptSig more +than 1650 bytes

+

Check the consensus + policy(if not disabled) rules that are not based +satisfaction

+

Check the consensus + policy(if not disabled) rules including the +ones for satisfaction

+

Check whether the top-level is type B

+

Other top level checks that are context specific

+

Check top level consensus rules.

+

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/type.KeyMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/type.KeyMap.html new file mode 100644 index 0000000000..83c07924bb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/keys/type.KeyMap.html @@ -0,0 +1,7 @@ +KeyMap in bdk_wallet::keys - Rust

Type Definition bdk_wallet::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 +public key from the descriptor.

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

Type Definition bdk_wallet::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_wallet/macro.descriptor!.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.descriptor!.html new file mode 100644 index 0000000000..976e018bd9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.descriptor!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.descriptor.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.descriptor.html new file mode 100644 index 0000000000..5cbb15e05d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.descriptor.html @@ -0,0 +1,81 @@ +descriptor in bdk_wallet - Rust

Macro bdk_wallet::descriptor

source ·
macro_rules! descriptor {
+    ( bare ( $( $minisc:tt )* ) ) => { ... };
+    ( sh ( wsh ( $( $minisc:tt )* ) ) ) => { ... };
+    ( shwsh ( $( $minisc:tt )* ) ) => { ... };
+    ( pk ( $key:expr ) ) => { ... };
+    ( pkh ( $key:expr ) ) => { ... };
+    ( wpkh ( $key:expr ) ) => { ... };
+    ( sh ( wpkh ( $key:expr ) ) ) => { ... };
+    ( shwpkh ( $key:expr ) ) => { ... };
+    ( sh ( $( $minisc:tt )* ) ) => { ... };
+    ( wsh ( $( $minisc:tt )* ) ) => { ... };
+    ( tr ( $internal_key:expr ) ) => { ... };
+    ( tr ( $internal_key:expr, $( $taptree:tt )* ) ) => { ... };
+}
+
Expand description

Macro to write full descriptors with code

+

This macro expands to a Result of +DescriptorTemplateOut and DescriptorError

+

The syntax is very similar to the normal descriptor syntax, with the exception that modifiers +cannot be grouped together. For instance, a descriptor fragment like sdv:older(144) has to be +broken up to s:d:v:older(144).

+

The pk(), pk_k() and pk_h() operands can take as argument any type that implements +IntoDescriptorKey. This means that keys can also be written inline as strings, but in that +case they must be wrapped in quotes, which is another difference compared to the standard +descriptor syntax.

+

Example

+

Signature plus timelock descriptor:

+ +
let (my_descriptor, my_keys_map, networks) = bdk_wallet::descriptor!(sh(wsh(and_v(v:pk("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"),older(50)))))?;
+
+

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.

+

They both produce the descriptor: wsh(thresh(2,pk(...),s:pk(...),sndv:older(...)))

+ +
let my_key_1 = bitcoin::PublicKey::from_str(
+    "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
+)?;
+let my_key_2 =
+    bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
+let my_timelock = 50;
+
+let (descriptor_a, key_map_a, networks) = bdk_wallet::descriptor! {
+    wsh (
+        thresh(2, pk(my_key_1), s:pk(my_key_2), s:n:d:v:older(my_timelock))
+    )
+}?;
+
+#[rustfmt::skip]
+let b_items = vec![
+    bdk_wallet::fragment!(pk(my_key_1))?,
+    bdk_wallet::fragment!(s:pk(my_key_2))?,
+    bdk_wallet::fragment!(s:n:d:v:older(my_timelock))?,
+];
+let (descriptor_b, mut key_map_b, networks) =
+    bdk_wallet::descriptor!(wsh(thresh_vec(2, b_items)))?;
+
+assert_eq!(descriptor_a, descriptor_b);
+assert_eq!(key_map_a.len(), key_map_b.len());
+
+

Simple 2-of-2 multi-signature, equivalent to: wsh(multi(2, ...))

+ +
let my_key_1 = bitcoin::PublicKey::from_str(
+    "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
+)?;
+let my_key_2 =
+    bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
+
+let (descriptor, key_map, networks) = bdk_wallet::descriptor! {
+    wsh (
+        multi(2, my_key_1, my_key_2)
+    )
+}?;
+
+

Native-Segwit single-sig, equivalent to: wpkh(...)

+ +
let my_key =
+    bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
+
+let (descriptor, key_map, networks) = bdk_wallet::descriptor!(wpkh(my_key))?;
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.fragment!.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.fragment!.html new file mode 100644 index 0000000000..6eeebba321 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.fragment!.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to macro.fragment.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.fragment.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.fragment.html new file mode 100644 index 0000000000..61db51d7ff --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/macro.fragment.html @@ -0,0 +1,36 @@ +fragment in bdk_wallet - Rust

Macro bdk_wallet::fragment

source ·
macro_rules! fragment {
+    ( $modif:tt : $( $tail:tt )* ) => { ... };
+    ( true ) => { ... };
+    ( false ) => { ... };
+    ( pk_k ( $key:expr ) ) => { ... };
+    ( pk ( $key:expr ) ) => { ... };
+    ( pk_h ( $key:expr ) ) => { ... };
+    ( after ( $value:expr ) ) => { ... };
+    ( older ( $value:expr ) ) => { ... };
+    ( sha256 ( $hash:expr ) ) => { ... };
+    ( hash256 ( $hash:expr ) ) => { ... };
+    ( ripemd160 ( $hash:expr ) ) => { ... };
+    ( hash160 ( $hash:expr ) ) => { ... };
+    ( and_v ( $( $inner:tt )* ) ) => { ... };
+    ( and_b ( $( $inner:tt )* ) ) => { ... };
+    ( and_or ( $( $inner:tt )* ) ) => { ... };
+    ( andor ( $( $inner:tt )* ) ) => { ... };
+    ( or_b ( $( $inner:tt )* ) ) => { ... };
+    ( or_d ( $( $inner:tt )* ) ) => { ... };
+    ( or_c ( $( $inner:tt )* ) ) => { ... };
+    ( or_i ( $( $inner:tt )* ) ) => { ... };
+    ( thresh_vec ( $thresh:expr, $items:expr ) ) => { ... };
+    ( thresh ( $thresh:expr, $( $inner:tt )* ) ) => { ... };
+    ( multi_vec ( $thresh:expr, $keys:expr ) ) => { ... };
+    ( multi ( $thresh:expr $(, $key:expr )+ ) ) => { ... };
+    ( multi_a_vec ( $thresh:expr, $keys:expr ) ) => { ... };
+    ( multi_a ( $thresh:expr $(, $key:expr )+ ) ) => { ... };
+    ( sortedmulti ( $( $inner:tt )* ) ) => { ... };
+    ( sortedmulti_vec ( $( $inner:tt )* ) ) => { ... };
+}
+
Expand description

Macro to write descriptor fragments with code

+

This macro will be expanded to an object of type Result<(Miniscript<DescriptorPublicKey, _>, KeyMap, ValidNetworks), DescriptorError>. It allows writing +fragments of larger descriptors that can be pieced together using fragment!(thresh_vec(m, ...)).

+

The syntax to write macro fragment is the same as documented for the descriptor macro.

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/psbt/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/psbt/index.html new file mode 100644 index 0000000000..16d76ca13f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/psbt/index.html @@ -0,0 +1,3 @@ +bdk_wallet::psbt - Rust

Module bdk_wallet::psbt

source ·
Expand description

Additional functions on the rust-bitcoin Psbt 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_wallet/psbt/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/psbt/sidebar-items.js new file mode 100644 index 0000000000..3b7a144401 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/psbt/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"trait":[["PsbtUtils","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_wallet/psbt/trait.PsbtUtils.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/psbt/trait.PsbtUtils.html new file mode 100644 index 0000000000..d99000f25f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/psbt/trait.PsbtUtils.html @@ -0,0 +1,14 @@ +PsbtUtils in bdk_wallet::psbt - Rust

Trait bdk_wallet::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. +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 +Psbt 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 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 new file mode 100644 index 0000000000..c3780c6996 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["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` `Psbt` structure."],["wallet","Wallet"]],"struct":[["LocalOutput","An unspent output owned by a `Wallet`."],["WeightedUtxo","A [`Utxo`] with its `satisfaction_weight`."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/struct.LocalOutput.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/struct.LocalOutput.html new file mode 100644 index 0000000000..ca4a4ba375 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/struct.LocalOutput.html @@ -0,0 +1,22 @@ +LocalOutput in bdk_wallet - Rust

Struct bdk_wallet::LocalOutput

source ·
pub struct LocalOutput {
+    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

+
§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.

+

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_wallet/struct.WeightedUtxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/struct.WeightedUtxo.html new file mode 100644 index 0000000000..3faad91d36 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/struct.WeightedUtxo.html @@ -0,0 +1,15 @@ +WeightedUtxo in bdk_wallet - Rust

Struct bdk_wallet::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 +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_wallet/types/enum.KeychainKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/enum.KeychainKind.html new file mode 100644 index 0000000000..7542d53230 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/enum.KeychainKind.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../bdk_wallet/enum.KeychainKind.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/enum.Utxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/enum.Utxo.html new file mode 100644 index 0000000000..8fd01f1eb7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/enum.Utxo.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../bdk_wallet/enum.Utxo.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/struct.LocalOutput.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/struct.LocalOutput.html new file mode 100644 index 0000000000..2ff675dcb0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/struct.LocalOutput.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../bdk_wallet/struct.LocalOutput.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/struct.WeightedUtxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/struct.WeightedUtxo.html new file mode 100644 index 0000000000..133d49e61a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/types/struct.WeightedUtxo.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../bdk_wallet/struct.WeightedUtxo.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/enum.Error.html new file mode 100644 index 0000000000..4a7984c8d4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/enum.Error.html @@ -0,0 +1,22 @@ +Error in bdk_wallet::wallet::coin_selection - Rust
pub enum Error {
+    InsufficientFunds {
+        needed: u64,
+        available: u64,
+    },
+    BnBNoExactMatch,
+    BnBTotalTriesExceeded,
+}
Expand description

Errors that can be thrown by the coin_selection module

+

Variants§

§

InsufficientFunds

Fields

§needed: u64

Sats needed for some transaction

+
§available: u64

Sats available for spending

+

Wallet’s UTXO set is not enough to cover recipient’s requested plus fee

+
§

BnBNoExactMatch

Branch and bound coin selection tries to avoid needing a change by finding the right inputs for +the desired outputs plus fee, if there is not such combination this error is thrown

+
§

BnBTotalTriesExceeded

Branch and bound coin selection possible attempts with sufficiently big UTXO set could grow +exponentially, thus a limit is set, and when hit, this error is thrown

+

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_wallet/wallet/coin_selection/enum.Excess.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/enum.Excess.html new file mode 100644 index 0000000000..b0487e7f71 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/enum.Excess.html @@ -0,0 +1,24 @@ +Excess in bdk_wallet::wallet::coin_selection - Rust
pub enum Excess {
+    NoChange {
+        dust_threshold: u64,
+        remaining_amount: u64,
+        change_fee: u64,
+    },
+    Change {
+        amount: u64,
+        fee: u64,
+    },
+}
Expand description

Remaining amount after performing coin selection

+

Variants§

§

NoChange

Fields

§dust_threshold: u64

Threshold to consider amount as dust for this particular change script_pubkey

+
§remaining_amount: u64

Exceeding amount of current selection over outgoing value and fee costs

+
§change_fee: u64

The calculated fee for the drain TxOut with the selected script_pubkey

+

It’s not possible to create spendable output from excess using the current drain output

+
§

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.

+

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_wallet/wallet/coin_selection/fn.decide_change.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/fn.decide_change.html new file mode 100644 index 0000000000..5c1c565c21 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/fn.decide_change.html @@ -0,0 +1,8 @@ +decide_change in bdk_wallet::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

+
    +
  • remaining_amount: the amount in which the selected coins exceed the target amount
  • +
  • fee_rate: required fee rate for the current selection
  • +
  • drain_script: script to consider change creation
  • +
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/index.html new file mode 100644 index 0000000000..b26ecedc7a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/index.html @@ -0,0 +1,75 @@ +bdk_wallet::wallet::coin_selection - Rust
Expand description

Coin selection

+

This module provides the trait CoinSelectionAlgorithm that can be implemented to +define custom coin selection algorithms.

+

You can specify a custom coin selection algorithm through the coin_selection method on +TxBuilder. DefaultCoinSelectionAlgorithm aliases the coin selection algorithm that will +be used if it is not explicitly set.

+

Example

+
#[derive(Debug)]
+struct AlwaysSpendEverything;
+
+impl CoinSelectionAlgorithm for AlwaysSpendEverything {
+    fn coin_select(
+        &self,
+        required_utxos: Vec<WeightedUtxo>,
+        optional_utxos: Vec<WeightedUtxo>,
+        fee_rate: FeeRate,
+        target_amount: u64,
+        drain_script: &Script,
+    ) -> Result<CoinSelectionResult, coin_selection::Error> {
+        let mut selected_amount = 0;
+        let mut additional_weight = Weight::ZERO;
+        let all_utxos_selected = required_utxos
+            .into_iter()
+            .chain(optional_utxos)
+            .scan(
+                (&mut selected_amount, &mut additional_weight),
+                |(selected_amount, additional_weight), weighted_utxo| {
+                    **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
+                    **additional_weight += Weight::from_wu(
+                        (TxIn::default().segwit_weight().to_wu()
+                            + weighted_utxo.satisfaction_weight as u64)
+                            as u64,
+                    );
+                    Some(weighted_utxo.utxo)
+                },
+            )
+            .collect::<Vec<_>>();
+        let additional_fees = (fee_rate * additional_weight).to_sat();
+        let amount_needed_with_fees = additional_fees + target_amount;
+        if selected_amount < amount_needed_with_fees {
+            return Err(coin_selection::Error::InsufficientFunds {
+                needed: amount_needed_with_fees,
+                available: selected_amount,
+            });
+        }
+
+        let remaining_amount = selected_amount - amount_needed_with_fees;
+
+        let excess = decide_change(remaining_amount, fee_rate, drain_script);
+
+        Ok(CoinSelectionResult {
+            selected: all_utxos_selected,
+            fee_amount: additional_fees,
+            excess,
+        })
+    }
+}
+
+// create wallet, sync, ...
+
+let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
+    .unwrap()
+    .require_network(Network::Testnet)
+    .unwrap();
+let psbt = {
+    let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
+    builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
+    builder.finish()?
+};
+
+// inspect, sign, broadcast, ...
+
+

Structs

Branch and bound coin selection
Result of a successful coin selection
Simple and dumb coin selection
OldestFirstCoinSelection always picks the utxo with the smallest blockheight to add to the selected coins next

Enums

Errors that can be thrown by the coin_selection module
Remaining amount after performing coin selection

Traits

Trait for generalized coin selection algorithms

Functions

Decide if change can be created

Type Definitions

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/wallet/coin_selection/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/sidebar-items.js new file mode 100644 index 0000000000..7ab6c39cfa --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["Error","Errors that can be thrown by the `coin_selection` module"],["Excess","Remaining amount after performing coin selection"]],"fn":[["decide_change","Decide if change can be created"]],"struct":[["BranchAndBoundCoinSelection","Branch and bound coin selection"],["CoinSelectionResult","Result of a successful coin selection"],["LargestFirstCoinSelection","Simple and dumb coin selection"],["OldestFirstCoinSelection","OldestFirstCoinSelection always picks the utxo with the smallest blockheight to add to the selected coins next"]],"trait":[["CoinSelectionAlgorithm","Trait for generalized coin selection algorithms"]],"type":[["DefaultCoinSelectionAlgorithm","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/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html new file mode 100644 index 0000000000..932452d3dd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html @@ -0,0 +1,9 @@ +BranchAndBoundCoinSelection in bdk_wallet::wallet::coin_selection - Rust
pub struct BranchAndBoundCoinSelection { /* private fields */ }
Expand description

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

+

Implementations§

Create new instance with target size for change output

+

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 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/wallet/coin_selection/struct.CoinSelectionResult.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/struct.CoinSelectionResult.html new file mode 100644 index 0000000000..298f7c5b77 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/struct.CoinSelectionResult.html @@ -0,0 +1,16 @@ +CoinSelectionResult in bdk_wallet::wallet::coin_selection - Rust
pub struct CoinSelectionResult {
+    pub selected: Vec<Utxo>,
+    pub fee_amount: u64,
+    pub excess: Excess,
+}
Expand description

Result of a successful coin selection

+

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.

+

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_wallet/wallet/coin_selection/struct.LargestFirstCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/struct.LargestFirstCoinSelection.html new file mode 100644 index 0000000000..527a0a31b9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/struct.LargestFirstCoinSelection.html @@ -0,0 +1,9 @@ +LargestFirstCoinSelection in bdk_wallet::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.

+

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_wallet/wallet/coin_selection/struct.OldestFirstCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/struct.OldestFirstCoinSelection.html new file mode 100644 index 0000000000..bf120b4221 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/struct.OldestFirstCoinSelection.html @@ -0,0 +1,9 @@ +OldestFirstCoinSelection in bdk_wallet::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.

+

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_wallet/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/trait.CoinSelectionAlgorithm.html new file mode 100644 index 0000000000..f85365e8a1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/trait.CoinSelectionAlgorithm.html @@ -0,0 +1,21 @@ +CoinSelectionAlgorithm in bdk_wallet::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

+
    +
  • database: a reference to the wallet’s database that can be used to lookup additional +details for a specific UTXO
  • +
  • required_utxos: the utxos that must be spent regardless of target_amount with their +weight cost
  • +
  • optional_utxos: the remaining available utxos to satisfy target_amount with their +weight cost
  • +
  • fee_rate: fee rate to use
  • +
  • target_amount: the outgoing amount in satoshis and the fees already +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 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html new file mode 100644 index 0000000000..9579299bd4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html @@ -0,0 +1,4 @@ +DefaultCoinSelectionAlgorithm in bdk_wallet::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/wallet/enum.ApplyBlockError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.ApplyBlockError.html new file mode 100644 index 0000000000..292a813416 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.ApplyBlockError.html @@ -0,0 +1,18 @@ +ApplyBlockError in bdk_wallet::wallet - Rust
pub enum ApplyBlockError {
+    CannotConnect(CannotConnectError),
+    UnexpectedConnectedToHash {
+        connected_to_hash: BlockHash,
+        expected_hash: BlockHash,
+    },
+}
Expand description

An error that may occur when applying a block to Wallet.

+

Variants§

§

CannotConnect(CannotConnectError)

Occurs when the update chain cannot connect with original chain.

+
§

UnexpectedConnectedToHash

Fields

§connected_to_hash: BlockHash

Block hash of connected_to.

+
§expected_hash: BlockHash

Expected block hash of connected_to, as derived from block.

+

Occurs when the connected_to hash does not match the hash derived from block.

+

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/wallet/enum.InsertTxError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.InsertTxError.html new file mode 100644 index 0000000000..da72cbd736 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.InsertTxError.html @@ -0,0 +1,17 @@ +InsertTxError in bdk_wallet::wallet - Rust
pub enum InsertTxError {
+    ConfirmationHeightCannotBeGreaterThanTip {
+        tip_height: u32,
+        tx_height: u32,
+    },
+}
Expand description

An error that may occur when inserting a transaction into Wallet.

+

Variants§

§

ConfirmationHeightCannotBeGreaterThanTip

Fields

§tip_height: u32

The internal chain’s tip height.

+
§tx_height: u32

The introduced transaction’s confirmation height.

+

The error variant that occurs when the caller attempts to insert a transaction with a +confirmation height that is greater than the internal chain tip.

+

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/wallet/enum.LoadError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.LoadError.html new file mode 100644 index 0000000000..cdef099fc6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.LoadError.html @@ -0,0 +1,22 @@ +LoadError in bdk_wallet::wallet - Rust
pub enum LoadError {
+    Descriptor(DescriptorError),
+    Persist(Error),
+    NotInitialized,
+    MissingNetwork,
+    MissingGenesis,
+    MissingDescriptor,
+}
Expand description

The error type when loading a Wallet from persistence.

+

Method load may return this error.

+

Variants§

§

Descriptor(DescriptorError)

There was a problem with the passed-in descriptor(s).

+
§

Persist(Error)

Loading data from the persistence backend failed.

+
§

NotInitialized

Wallet not initialized, persistence backend is empty.

+
§

MissingNetwork

Data loaded from persistence is missing network type.

+
§

MissingGenesis

Data loaded from persistence is missing genesis hash.

+
§

MissingDescriptor

Data loaded from persistence is missing descriptor.

+

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/wallet/enum.NewError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.NewError.html new file mode 100644 index 0000000000..22bf638de6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.NewError.html @@ -0,0 +1,16 @@ +NewError in bdk_wallet::wallet - Rust

Enum bdk_wallet::wallet::NewError

source ·
pub enum NewError {
+    NonEmptyDatabase,
+    Descriptor(DescriptorError),
+    Persist(Error),
+}
Expand description

The error type when constructing a fresh Wallet.

+

Methods new and new_with_genesis_hash may return this error.

+

Variants§

§

NonEmptyDatabase

Database already has data.

+
§

Descriptor(DescriptorError)

There was problem with the passed-in descriptor(s).

+
§

Persist(Error)

We were unable to write the wallet’s data to the persistence 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/wallet/enum.NewOrLoadError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.NewOrLoadError.html new file mode 100644 index 0000000000..401feb0740 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/enum.NewOrLoadError.html @@ -0,0 +1,37 @@ +NewOrLoadError in bdk_wallet::wallet - Rust
pub enum NewOrLoadError {
+    Descriptor(DescriptorError),
+    Persist(Error),
+    NotInitialized,
+    LoadedGenesisDoesNotMatch {
+        expected: BlockHash,
+        got: Option<BlockHash>,
+    },
+    LoadedNetworkDoesNotMatch {
+        expected: Network,
+        got: Option<Network>,
+    },
+    LoadedDescriptorDoesNotMatch {
+        got: Option<ExtendedDescriptor>,
+        keychain: KeychainKind,
+    },
+}
Expand description

Error type for when we try load a Wallet from persistence and creating it if non-existent.

+

Methods new_or_load and new_or_load_with_genesis_hash may return this error.

+

Variants§

§

Descriptor(DescriptorError)

There is a problem with the passed-in descriptor.

+
§

Persist(Error)

Either writing to or loading from the persistence backend failed.

+
§

NotInitialized

Wallet is not initialized, persistence backend is empty.

+
§

LoadedGenesisDoesNotMatch

Fields

§expected: BlockHash

The expected genesis block hash.

+
§got: Option<BlockHash>

The block hash loaded from persistence.

+

The loaded genesis hash does not match what was provided.

+
§

LoadedNetworkDoesNotMatch

Fields

§expected: Network

The expected network type.

+
§got: Option<Network>

The network type loaded from persistence.

+

The loaded network type does not match what was provided.

+
§

LoadedDescriptorDoesNotMatch

Fields

§got: Option<ExtendedDescriptor>

The descriptor loaded from persistence.

+
§keychain: KeychainKind

The keychain of the descriptor not matching

+

The loaded desccriptor does not match what was provided.

+

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/wallet/error/enum.BuildFeeBumpError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/enum.BuildFeeBumpError.html new file mode 100644 index 0000000000..818b6ccdc1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/enum.BuildFeeBumpError.html @@ -0,0 +1,19 @@ +BuildFeeBumpError in bdk_wallet::wallet::error - Rust
pub enum BuildFeeBumpError {
+    UnknownUtxo(OutPoint),
+    TransactionNotFound(Txid),
+    TransactionConfirmed(Txid),
+    IrreplaceableTransaction(Txid),
+    FeeRateUnavailable,
+}
Expand description

Error returned from Wallet::build_fee_bump

+

Variants§

§

UnknownUtxo(OutPoint)

Happens when trying to spend an UTXO that is not in the internal database

+
§

TransactionNotFound(Txid)

Thrown when a tx is not found in the internal database

+
§

TransactionConfirmed(Txid)

Happens when trying to bump a transaction that is already confirmed

+
§

IrreplaceableTransaction(Txid)

Trying to replace a tx that has a sequence >= 0xFFFFFFFE

+
§

FeeRateUnavailable

Node doesn’t have data to estimate a fee rate

+

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/wallet/error/enum.CreateTxError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/enum.CreateTxError.html new file mode 100644 index 0000000000..f4c72a68b6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/enum.CreateTxError.html @@ -0,0 +1,76 @@ +CreateTxError in bdk_wallet::wallet::error - Rust
pub enum CreateTxError {
+
Show 22 variants Descriptor(DescriptorError), + Persist(Error), + Policy(PolicyError), + SpendingPolicyRequired(KeychainKind), + Version0, + Version1Csv, + LockTime { + requested: LockTime, + required: LockTime, + }, + RbfSequence, + RbfSequenceCsv { + rbf: Sequence, + csv: Sequence, + }, + FeeTooLow { + required: u64, + }, + FeeRateTooLow { + required: FeeRate, + }, + NoUtxosSelected, + OutputBelowDustLimit(usize), + ChangePolicyDescriptor, + CoinSelection(Error), + InsufficientFunds { + needed: u64, + available: u64, + }, + NoRecipients, + Psbt(Error), + MissingKeyOrigin(String), + UnknownUtxo, + MissingNonWitnessUtxo(OutPoint), + MiniscriptPsbt(MiniscriptPsbtError), +
}
Expand description

Error returned from TxBuilder::finish

+

Variants§

§

Descriptor(DescriptorError)

There was a problem with the descriptors passed in

+
§

Persist(Error)

We were unable to load wallet data from or write wallet data to the persistence backend

+
§

Policy(PolicyError)

There was a problem while extracting and manipulating policies

+
§

SpendingPolicyRequired(KeychainKind)

Spending policy is not compatible with this KeychainKind

+
§

Version0

Requested invalid transaction version ‘0’

+
§

Version1Csv

Requested transaction version 1, but at least 2 is needed to use OP_CSV

+
§

LockTime

Fields

§requested: LockTime

Requested LockTime

+
§required: LockTime

Required LockTime

+

Requested LockTime is less than is required to spend from this script

+
§

RbfSequence

Cannot enable RBF with a Sequence >= 0xFFFFFFFE

+
§

RbfSequenceCsv

Fields

§rbf: Sequence

Given RBF Sequence

+
§csv: Sequence

Required OP_CSV Sequence

+

Cannot enable RBF with Sequence given a required OP_CSV

+
§

FeeTooLow

Fields

§required: u64

Required fee absolute value (satoshi)

+

When bumping a tx the absolute fee requested is lower than replaced tx absolute fee

+
§

FeeRateTooLow

Fields

§required: FeeRate

Required fee rate

+

When bumping a tx the fee rate requested is lower than required

+
§

NoUtxosSelected

manually_selected_only option is selected but no utxo has been passed

+
§

OutputBelowDustLimit(usize)

Output created is under the dust limit, 546 satoshis

+
§

ChangePolicyDescriptor

The change_policy was set but the wallet does not have a change_descriptor

+
§

CoinSelection(Error)

There was an error with coin selection

+
§

InsufficientFunds

Fields

§needed: u64

Sats needed for some transaction

+
§available: u64

Sats available for spending

+

Wallet’s UTXO set is not enough to cover recipient’s requested plus fee

+
§

NoRecipients

Cannot build a tx without recipients

+
§

Psbt(Error)

Partially signed bitcoin transaction error

+
§

MissingKeyOrigin(String)

In order to use the TxBuilder::add_global_xpubs option every extended +key in the descriptor must either be a master key itself (having depth = 0) or have an +explicit origin provided

+
§

UnknownUtxo

Happens when trying to spend an UTXO that is not in the internal database

+
§

MissingNonWitnessUtxo(OutPoint)

Missing non_witness_utxo on foreign utxo for given OutPoint

+
§

MiniscriptPsbt(MiniscriptPsbtError)

Miniscript PSBT 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.

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/wallet/error/enum.MiniscriptPsbtError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/enum.MiniscriptPsbtError.html new file mode 100644 index 0000000000..9e33111d11 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/enum.MiniscriptPsbtError.html @@ -0,0 +1,15 @@ +MiniscriptPsbtError in bdk_wallet::wallet::error - Rust
pub enum MiniscriptPsbtError {
+    Conversion(ConversionError),
+    UtxoUpdate(UtxoUpdateError),
+    OutputUpdate(OutputUpdateError),
+}
Expand description

Errors returned by miniscript when updating inconsistent PSBTs

+

Variants§

§

Conversion(ConversionError)

Descriptor key conversion error

+
§

UtxoUpdate(UtxoUpdateError)

Return error type for PsbtExt::update_input_with_descriptor

+
§

OutputUpdate(OutputUpdateError)

Return error type for PsbtExt::update_output_with_descriptor

+

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.

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_wallet/wallet/error/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/index.html new file mode 100644 index 0000000000..4921cedf62 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/index.html @@ -0,0 +1,3 @@ +bdk_wallet::wallet::error - Rust

Module bdk_wallet::wallet::error

source ·
Expand description

Errors that can be thrown by the Wallet

+

Enums

Error returned from TxBuilder::finish
Errors returned by miniscript when updating inconsistent PSBTs
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/sidebar-items.js new file mode 100644 index 0000000000..4f379f6341 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/error/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["BuildFeeBumpError","Error returned from `Wallet::build_fee_bump`"],["CreateTxError","Error returned from `TxBuilder::finish`"],["MiniscriptPsbtError","Errors returned by miniscript when updating inconsistent PSBTs"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/index.html new file mode 100644 index 0000000000..0d0bccdd41 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/index.html @@ -0,0 +1,26 @@ +bdk_wallet::wallet::export - Rust

Module bdk_wallet::wallet::export

source ·
Expand description

Wallet export

+

This modules implements the wallet export format used by FullyNoded.

+

Examples

Import from JSON

+
let import = r#"{
+    "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
+    "blockheight":1782088,
+    "label":"testnet"
+}"#;
+
+let import = FullyNodedExport::from_str(import)?;
+let wallet = Wallet::new_no_persist(
+    &import.descriptor(),
+    import.change_descriptor().as_ref(),
+    Network::Testnet,
+)?;
+

Export a Wallet

+
let wallet = Wallet::new_no_persist(
+    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+    Network::Testnet,
+)?;
+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/wallet/export/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/sidebar-items.js new file mode 100644 index 0000000000..07ee950354 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"struct":[["FullyNodedExport","Structure that contains the export of a wallet"]],"type":[["WalletExport","Alias for [`FullyNodedExport`]"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/struct.FullyNodedExport.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/struct.FullyNodedExport.html new file mode 100644 index 0000000000..3a9b74ead4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/struct.FullyNodedExport.html @@ -0,0 +1,24 @@ +FullyNodedExport in bdk_wallet::wallet::export - Rust
pub struct FullyNodedExport {
+    pub blockheight: u32,
+    pub label: String,
+    /* private fields */
+}
Expand description

Structure that contains the export of a wallet

+

For a usage example see this module’s documentation.

+

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

+

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.

+

If include_blockheight is true, this function will look into the wallet’s database +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
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
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.

+
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/wallet/export/type.WalletExport.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/type.WalletExport.html new file mode 100644 index 0000000000..0410ec89e8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/export/type.WalletExport.html @@ -0,0 +1,3 @@ +WalletExport in bdk_wallet::wallet::export - Rust

Type Definition bdk_wallet::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/wallet/fn.wallet_name_from_descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/fn.wallet_name_from_descriptor.html new file mode 100644 index 0000000000..8f3a3341aa --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/fn.wallet_name_from_descriptor.html @@ -0,0 +1,4 @@ +wallet_name_from_descriptor in bdk_wallet::wallet - Rust
pub fn wallet_name_from_descriptor<T>(
    descriptor: T,
    change_descriptor: Option<T>,
    network: Network,
    secp: &Secp256k1<All>
) -> Result<String, DescriptorError>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/wallet/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/index.html new file mode 100644 index 0000000000..5a56905443 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/index.html @@ -0,0 +1,7 @@ +bdk_wallet::wallet - Rust

Module bdk_wallet::wallet

source ·
Expand description

Wallet

+

This module defines the Wallet.

+

Modules

Coin selection
Errors that can be thrown by the Wallet
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 into various categories.
The changes made to a wallet by applying an Update.
An update to Wallet.
A Bitcoin wallet

Enums

An error that may occur when applying a block to Wallet.
An error that may occur when inserting a transaction into Wallet.
The error type when loading a Wallet from persistence.
The error type when constructing a fresh Wallet.
Error type for when we try load a Wallet from persistence and creating it if non-existent.

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

Deterministically generate a unique name given the descriptors defining the wallet
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/sidebar-items.js new file mode 100644 index 0000000000..b5896f9a0d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["ApplyBlockError","An error that may occur when applying a block to [`Wallet`]."],["InsertTxError","An error that may occur when inserting a transaction into [`Wallet`]."],["LoadError","The error type when loading a [`Wallet`] from persistence."],["NewError","The error type when constructing a fresh [`Wallet`]."],["NewOrLoadError","Error type for when we try load a [`Wallet`] from persistence and creating it if non-existent."]],"fn":[["wallet_name_from_descriptor","Deterministically generate a unique name given the descriptors defining the wallet"]],"mod":[["coin_selection","Coin selection"],["error","Errors that can be thrown by the `Wallet`"],["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 into various categories."],["ChangeSet","The changes made to a wallet by applying an [`Update`]."],["Update","An update to [`Wallet`]."],["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 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/enum.SignerContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/enum.SignerContext.html new file mode 100644 index 0000000000..c38d4b272e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/enum.SignerContext.html @@ -0,0 +1,20 @@ +SignerContext in bdk_wallet::wallet::signer - Rust
pub enum SignerContext {
+    Legacy,
+    Segwitv0,
+    Tap {
+        is_internal_key: bool,
+    },
+}
Expand description

Signing context

+

Used by our software signers to determine the type of signatures to make

+

Variants§

§

Legacy

Legacy context

+
§

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 +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_wallet/wallet/signer/enum.SignerError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/enum.SignerError.html new file mode 100644 index 0000000000..a3aad6ad43 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/enum.SignerError.html @@ -0,0 +1,42 @@ +SignerError in bdk_wallet::wallet::signer - Rust
pub enum SignerError {
+
Show 14 variants MissingKey, + InvalidKey, + UserCanceled, + InputIndexOutOfRange, + MissingNonWitnessUtxo, + InvalidNonWitnessUtxo, + MissingWitnessUtxo, + MissingWitnessScript, + MissingHdKeypath, + NonStandardSighash, + InvalidSighash, + SighashError(Error), + MiniscriptPsbt(MiniscriptPsbtError), + External(String), +
}
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

+
§

InputIndexOutOfRange

Input index is out of range

+
§

MissingNonWitnessUtxo

The non_witness_utxo field of the transaction is required to sign this input

+
§

InvalidNonWitnessUtxo

The non_witness_utxo specified is invalid

+
§

MissingWitnessUtxo

The witness_utxo field of the transaction is required to sign this input

+
§

MissingWitnessScript

The witness_script field of the transaction is required to sign this input

+
§

MissingHdKeypath

The fingerprint and derivation path are missing from the psbt input

+
§

NonStandardSighash

The psbt contains a non-SIGHASH_ALL sighash in one of its input and the user hasn’t +explicitly allowed them

+

To enable signing transactions with non-standard sighashes set +SignOptions::allow_all_sighashes to true.

+
§

InvalidSighash

Invalid SIGHASH for the signing context in use

+
§

SighashError(Error)

Error while computing the hash to sign

+
§

MiniscriptPsbt(MiniscriptPsbtError)

Miniscript PSBT error

+
§

External(String)

To be used only by external libraries implementing InputSigner or +TransactionSigner, so that they can return their own custom errors, without having to +modify SignerError in BDK.

+

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_wallet/wallet/signer/enum.SignerId.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/enum.SignerId.html new file mode 100644 index 0000000000..4329f64057 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/enum.SignerId.html @@ -0,0 +1,19 @@ +SignerId in bdk_wallet::wallet::signer - Rust
pub enum SignerId {
+    PkHash(Hash),
+    Fingerprint(Fingerprint),
+    Dummy(u64),
+}
Expand description

Identifier of a signer in the SignersContainers. Used as a key to find the right signer among +multiple of them

+

Variants§

§

PkHash(Hash)

Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA public key

+
§

Fingerprint(Fingerprint)

The fingerprint of a BIP32 extended key

+
§

Dummy(u64)

Dummy identifier

+

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.
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

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_wallet/wallet/signer/enum.TapLeavesOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/enum.TapLeavesOptions.html new file mode 100644 index 0000000000..07f9925354 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/enum.TapLeavesOptions.html @@ -0,0 +1,19 @@ +TapLeavesOptions in bdk_wallet::wallet::signer - Rust
pub enum TapLeavesOptions {
+    All,
+    Include(Vec<TapLeafHash>),
+    Exclude(Vec<TapLeafHash>),
+    None,
+}
Expand description

Customize which taproot script-path leaves the signer should sign.

+

Variants§

§

All

The signer will sign all the leaves it has a key for.

+
§

Include(Vec<TapLeafHash>)

The signer won’t sign leaves other than the ones specified. Note that it could still ignore +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 +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_wallet/wallet/signer/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/index.html new file mode 100644 index 0000000000..35df8ea571 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/index.html @@ -0,0 +1,48 @@ +bdk_wallet::wallet::signer - Rust

Module bdk_wallet::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.

+ +
#[derive(Debug)]
+struct CustomSigner {
+    device: CustomHSM,
+}
+
+impl CustomSigner {
+    fn connect() -> Self {
+        CustomSigner { device: CustomHSM::connect() }
+    }
+}
+
+impl SignerCommon for CustomSigner {
+    fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
+        self.device.get_id()
+    }
+}
+
+impl InputSigner for CustomSigner {
+    fn sign_input(
+        &self,
+        psbt: &mut Psbt,
+        input_index: usize,
+        _sign_options: &SignOptions,
+        _secp: &Secp256k1<All>,
+    ) -> Result<(), SignerError> {
+        self.device.hsm_sign_input(psbt, input_index)?;
+
+        Ok(())
+    }
+}
+
+let custom_signer = CustomSigner::connect();
+
+let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+let mut wallet = Wallet::new_no_persist(descriptor, None, Network::Testnet)?;
+wallet.add_signer(
+    KeychainKind::External,
+    SignerOrdering(200),
+    Arc::new(custom_signer)
+);
+
+

Structs

Options for a software signer
Defines the order in which signers are called
Wrapper to pair a signer with its context
Container for multiple signers

Enums

Signing context
Signing error
Identifier of a signer in the SignersContainers. Used as a key to find the right signer among +multiple of them
Customize which taproot script-path leaves the signer should sign.

Traits

PSBT Input signer
Common signer methods
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/sidebar-items.js new file mode 100644 index 0000000000..34ced712cb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["SignerContext","Signing context"],["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"],["TapLeavesOptions","Customize which taproot script-path leaves the signer should sign."]],"struct":[["SignOptions","Options for a software signer"],["SignerOrdering","Defines the order in which signers are called"],["SignerWrapper","Wrapper to pair a signer with its context"],["SignersContainer","Container for multiple signers"]],"trait":[["InputSigner","PSBT Input signer"],["SignerCommon","Common signer methods"],["TransactionSigner","PSBT signer"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/struct.SignOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/struct.SignOptions.html new file mode 100644 index 0000000000..3bf8e48031 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/struct.SignOptions.html @@ -0,0 +1,53 @@ +SignOptions in bdk_wallet::wallet::signer - Rust
pub struct SignOptions {
+    pub trust_witness_utxo: bool,
+    pub assume_height: Option<u32>,
+    pub allow_all_sighashes: bool,
+    pub remove_partial_sigs: bool,
+    pub remove_taproot_extras: bool,
+    pub try_finalize: bool,
+    pub tap_leaves_options: TapLeavesOptions,
+    pub sign_with_tap_internal_key: bool,
+    pub allow_grinding: bool,
+}
Expand description

Options for a software signer

+

Adjust the behavior of our software signers and the way a transaction is finalized

+

Fields§

§trust_witness_utxo: bool

Whether the signer should trust the witness_utxo, if the non_witness_utxo hasn’t been +provided

+

Defaults to false to mitigate the “SegWit bug” which should trick the wallet into +paying a fee larger than expected.

+

Some wallets, especially if relatively old, might not provide the non_witness_utxo for +SegWit transactions in the PSBT they generate: in those cases setting this to true +should correctly produce a signature, at the expense of an increased trust in the creator +of the PSBT.

+

For more details see: https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd

+
§assume_height: Option<u32>

Whether the wallet should assume a specific height has been reached when trying to finalize +a transaction

+

The wallet will only “use” a timelock to satisfy the spending policy of an input if the +timelock height has already been reached. This option allows overriding the “current height” to let the +wallet use timelocks in the future to spend a coin.

+
§allow_all_sighashes: bool

Whether the signer should use the sighash_type set in the PSBT when signing, no matter +what its value is

+

Defaults to false which will only allow signing using SIGHASH_ALL.

+
§remove_partial_sigs: bool

Whether to remove partial signatures from the PSBT inputs while finalizing PSBT.

+

Defaults to true which will remove partial signatures during finalization.

+
§remove_taproot_extras: bool

Whether to remove taproot specific fields from the PSBT on finalization.

+

For inputs this includes the taproot internal key, merkle root, and individual +scripts and signatures. For both inputs and outputs it includes key origin info.

+

Defaults to true which will remove all of the above mentioned fields when finalizing.

+

See BIP371 for details.

+
§try_finalize: bool

Whether to try finalizing the PSBT after the inputs are signed.

+

Defaults to true which will try finalizing PSBT after inputs are signed.

+
§tap_leaves_options: TapLeavesOptions

Specifies which Taproot script-spend leaves we should sign for. This option is +ignored if we’re signing a non-taproot PSBT.

+

Defaults to All, i.e., the wallet will sign all the leaves it has a key for.

+
§sign_with_tap_internal_key: bool

Whether we should try to sign a taproot transaction with the taproot internal key +or not. This option is ignored if we’re signing a non-taproot PSBT.

+

Defaults to true, i.e., we always try to sign with the taproot internal key.

+
§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.

+

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_wallet/wallet/signer/struct.SignerOrdering.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/struct.SignerOrdering.html new file mode 100644 index 0000000000..a1567a080b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/struct.SignerOrdering.html @@ -0,0 +1,14 @@ +SignerOrdering in bdk_wallet::wallet::signer - Rust
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 +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
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/wallet/signer/struct.SignerWrapper.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/struct.SignerWrapper.html new file mode 100644 index 0000000000..6c8fae5687 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/struct.SignerWrapper.html @@ -0,0 +1,8 @@ +SignerWrapper in bdk_wallet::wallet::signer - Rust
pub struct SignerWrapper<S: Sized + Debug + Clone> { /* private fields */ }
Expand description

Wrapper 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
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
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 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/wallet/signer/struct.SignersContainer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/struct.SignersContainer.html new file mode 100644 index 0000000000..c5899df539 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/struct.SignersContainer.html @@ -0,0 +1,18 @@ +SignersContainer in bdk_wallet::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 +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.

+

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_wallet/wallet/signer/trait.InputSigner.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/trait.InputSigner.html new file mode 100644 index 0000000000..34e9198b46 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/trait.InputSigner.html @@ -0,0 +1,9 @@ +InputSigner in bdk_wallet::wallet::signer - Rust
pub trait InputSigner: SignerCommon {
+    fn sign_input(
        &self,
        psbt: &mut Psbt,
        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 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/trait.SignerCommon.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/trait.SignerCommon.html new file mode 100644 index 0000000000..3b060a2e2f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/trait.SignerCommon.html @@ -0,0 +1,14 @@ +SignerCommon in bdk_wallet::wallet::signer - Rust
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

+

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

+

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 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/trait.TransactionSigner.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/trait.TransactionSigner.html new file mode 100644 index 0000000000..3989987fe9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/signer/trait.TransactionSigner.html @@ -0,0 +1,8 @@ +TransactionSigner in bdk_wallet::wallet::signer - Rust
pub trait TransactionSigner: SignerCommon {
+    fn sign_transaction(
        &self,
        psbt: &mut Psbt,
        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§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.AddressInfo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.AddressInfo.html new file mode 100644 index 0000000000..355bbf06e7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.AddressInfo.html @@ -0,0 +1,77 @@ +AddressInfo in bdk_wallet::wallet - Rust

Struct bdk_wallet::wallet::AddressInfo

source ·
pub struct AddressInfo {
+    pub index: u32,
+    pub address: Address,
+    pub keychain: KeychainKind,
+}
Expand description

A derived address and the index it was found at. +For convenience this automatically derefs to Address

+

Fields§

§index: u32

Child index of this address

+
§address: Address

Address

+
§keychain: KeychainKind

Type of keychain

+

Methods from Deref<Target = Address>§

Returns a reference to the payload of this address.

+

Returns a reference to the network of this address.

+

Returns a reference to the unchecked address, which is dangerous to use if the address +is invalid in the context of NetworkUnchecked.

+

Gets the address type of the address.

+
Returns
+

None if unknown, non-standard or related to the future witness version.

+

Checks whether or not the address is following Bitcoin standardness rules when +spending from this address. NOT to be called by senders.

+
+Spending Standardness +

For forward compatibility, the senders must send to any [Address]. Receivers +can use this method to check whether or not they can spend from this address.

+

SegWit addresses with unassigned witness versions or non-standard program sizes are +considered non-standard.

+
+

Generates a script pubkey spending to this address.

+

Creates a URI string bitcoin:address optimized to be encoded in QR codes.

+

If the address is bech32, the address becomes uppercase. +If the address is base58, the address is left mixed case.

+

Quoting BIP 173 “inside QR codes uppercase SHOULD be used, as those permit the use of +alphanumeric mode, which is 45% more compact than the normal byte mode.”

+

Note however that despite BIP21 explicitly stating that the bitcoin: prefix should be +parsed as case-insensitive many wallets got this wrong and don’t parse correctly. +See compatibility table.

+

If you want to avoid allocation you can use alternate display instead:

+ +

+write!(writer, "{:#}", address)?;
+
+

Returns true if the given pubkey is directly related to the address payload.

+

This is determined by directly comparing the address payload with either the +hash of the given public key or the segwit redeem hash generated from the +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.

+

Returns true if the address creates a particular script +This function doesn’t make any allocations.

+

Returns a reference to the checked address. +This function is dangerous in case the address is not a valid checked address.

+

Parsed addresses do not always have one network. The problem is that legacy testnet, +regtest and signet addresse use the same prefix instead of multiple different ones. When +parsing, such addresses are always assumed to be testnet addresses (the same is true for +bech32 signet addresses). So if one wants to check if an address belongs to a certain +network a simple comparison is not enough anymore. Instead this function can be used.

+ +
use bitcoin::{Address, Network};
+use bitcoin::address::NetworkUnchecked;
+
+let address: Address<NetworkUnchecked> = "2N83imGV3gPwBzKJQvWJ7cRUY2SpUyU6A5e".parse().unwrap();
+assert!(address.is_valid_for_network(Network::Testnet));
+assert!(address.is_valid_for_network(Network::Regtest));
+assert!(address.is_valid_for_network(Network::Signet));
+
+assert_eq!(address.is_valid_for_network(Network::Bitcoin), false);
+
+let address: Address<NetworkUnchecked> = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap();
+assert!(address.is_valid_for_network(Network::Bitcoin));
+assert_eq!(address.is_valid_for_network(Network::Testnet), false);
+

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.

+

Calls U::from(self).

+

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

+
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/wallet/struct.Balance.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.Balance.html new file mode 100644 index 0000000000..e5159769af --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.Balance.html @@ -0,0 +1,22 @@ +Balance in bdk_wallet::wallet - Rust

Struct bdk_wallet::wallet::Balance

pub struct Balance {
+    pub immature: Amount,
+    pub trusted_pending: Amount,
+    pub untrusted_pending: Amount,
+    pub confirmed: Amount,
+}
Expand description

Balance, differentiated into various categories.

+

Fields§

§immature: Amount

All coinbase outputs not yet matured

+
§trusted_pending: Amount

Unconfirmed UTXOs generated by a wallet tx

+
§untrusted_pending: Amount

Unconfirmed UTXOs received from an external wallet

+
§confirmed: Amount

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/wallet/struct.ChangeSet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.ChangeSet.html new file mode 100644 index 0000000000..d8379c75f1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.ChangeSet.html @@ -0,0 +1,16 @@ +ChangeSet in bdk_wallet::wallet - Rust

Struct bdk_wallet::wallet::ChangeSet

source ·
pub struct ChangeSet {
+    pub chain: ChangeSet,
+    pub indexed_tx_graph: ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>,
+    pub network: Option<Network>,
+}
Expand description

The changes made to a wallet by applying an Update.

+

Fields§

§chain: ChangeSet

Changes to the LocalChain.

+
§indexed_tx_graph: ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>

Changes to IndexedTxGraph.

+
§network: Option<Network>

Stores the network type of the wallet.

+

Trait Implementations§

Append another object of the same type onto self.
Returns whether the structure is considered empty.
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.
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_wallet/wallet/struct.Update.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.Update.html new file mode 100644 index 0000000000..b7a9c546db --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.Update.html @@ -0,0 +1,16 @@ +Update in bdk_wallet::wallet - Rust

Struct bdk_wallet::wallet::Update

source ·
pub struct Update {
+    pub last_active_indices: BTreeMap<KeychainKind, u32>,
+    pub graph: TxGraph<ConfirmationTimeHeightAnchor>,
+    pub chain: Option<CheckPoint>,
+}
Expand description

An update to Wallet.

+

It updates [bdk_chain::keychain::KeychainTxOutIndex], [bdk_chain::TxGraph] and [local_chain::LocalChain] atomically.

+

Fields§

§last_active_indices: BTreeMap<KeychainKind, u32>

Contains the last active derivation indices per keychain (K), which is used to update the +[KeychainTxOutIndex].

+
§graph: TxGraph<ConfirmationTimeHeightAnchor>

Update for the wallet’s internal [TxGraph].

+
§chain: Option<CheckPoint>

Update for the wallet’s internal LocalChain.

+

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
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 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/wallet/struct.Wallet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.Wallet.html new file mode 100644 index 0000000000..ad9809f576 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/struct.Wallet.html @@ -0,0 +1,314 @@ +Wallet in bdk_wallet::wallet - Rust

Struct bdk_wallet::wallet::Wallet

source ·
pub struct Wallet { /* private fields */ }
Expand description

A Bitcoin wallet

+

The Wallet 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. signers that can contribute signatures to addresses instantiated from the descriptors.
  4. +
+

Implementations§

Creates a wallet that does not persist data.

+

Creates a wallet that does not persist data, with a custom genesis hash.

+

Initialize an empty Wallet.

+

Initialize an empty Wallet with a custom genesis hash.

+

This is like Wallet::new with an additional genesis_hash parameter. This is useful +for syncing from alternative networks.

+

Load Wallet from the given persistence backend.

+

Note that the descriptor secret keys are not persisted to the db; this means that after +calling this method the Wallet won’t know the secret keys, and as such, won’t be +able to sign transactions.

+

If you wish to use the wallet to sign transactions, you need to add the secret keys +manually to the Wallet:

+ +
let secp = Secp256k1::new();
+
+let (external_descriptor, external_keymap) = Descriptor::parse_descriptor(&secp, "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)").unwrap();
+let (internal_descriptor, internal_keymap) = Descriptor::parse_descriptor(&secp, "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)").unwrap();
+
+let external_signer_container = SignersContainer::build(external_keymap, &external_descriptor, &secp);
+let internal_signer_container = SignersContainer::build(internal_keymap, &internal_descriptor, &secp);
+
+let mut wallet = Wallet::load(db)?;
+
+external_signer_container.signers().into_iter()
+    .for_each(|s| wallet.add_signer(KeychainKind::External, SignerOrdering::default(), s.clone()));
+internal_signer_container.signers().into_iter()
+    .for_each(|s| wallet.add_signer(KeychainKind::Internal, SignerOrdering::default(), s.clone()));
+

Alternatively, you can call Wallet::new_or_load, which will add the private keys of the +passed-in descriptors to the Wallet.

+

Either loads Wallet from persistence, or initializes it if it does not exist.

+

This method will fail if the loaded Wallet has different parameters to those provided.

+

Either loads Wallet from persistence, or initializes it if it does not exist, using the +provided descriptor, change descriptor, network, and custom genesis hash.

+

This method will fail if the loaded Wallet has different parameters to those provided. +This is like Wallet::new_or_load with an additional genesis_hash parameter. This is +useful for syncing from alternative networks.

+

Get the Bitcoin network the wallet is using.

+

Iterator over all keychains in this wallet

+

Peek an address of the given keychain at index without revealing it.

+

For non-wildcard descriptors this returns the same address at every provided index.

+
Panics
+

This panics when the caller requests for an address of derivation index greater than the +BIP32 max index.

+

Attempt to reveal the next address of the given keychain.

+

This will increment the internal derivation index. If the keychain’s descriptor doesn’t +contain a wildcard or every address is already revealed up to the maximum derivation +index defined in BIP32, +then returns the last revealed address.

+
Errors
+

If writing to persistent storage fails.

+

Reveal addresses up to and including the target index and return an iterator +of newly revealed addresses.

+

If the target index is unreachable, we make a best effort to reveal up to the last +possible index. If all addresses up to the given index are already revealed, then +no new addresses are returned.

+
Errors
+

If writing to persistent storage fails.

+

Get the next unused address for the given keychain, i.e. the address with the lowest +derivation index that hasn’t been used.

+

This will attempt to derive and reveal a new address if no newly revealed addresses +are available. See also reveal_next_address.

+
Errors
+

If writing to persistent storage fails.

+

Marks an address used of the given keychain at index.

+

Returns whether the given index was present and then removed from the unused set.

+

Undoes the effect of mark_used and returns whether the index was inserted +back into the unused set.

+

Since this is only a superficial marker, it will have no effect if the address at the given +index was actually used, i.e. the wallet has previously indexed a tx output for the +derived spk.

+

List addresses that are revealed but unused.

+

Note if the returned iterator is empty you can reveal more addresses +by using reveal_next_address or +reveal_addresses_to.

+

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

+

List all relevant outputs (includes both spent and unspent, confirmed and unconfirmed).

+

To list only unspent outputs (UTXOs), use Wallet::list_unspent instead.

+

Get all the checkpoints the wallet is currently storing indexed by height.

+

Returns the latest checkpoint.

+

Get unbounded script pubkey iterators for both Internal and External keychains.

+

This is intended 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 gap.

+

Note carefully that iterators go over all script pubkeys on the keychains (not what +script pubkeys the wallet is storing internally).

+

Get an unbounded script pubkey iterator for the given keychain.

+

See all_unbounded_spk_iters for more documentation

+

Returns the utxo owned by this wallet corresponding to outpoint if it exists in the +wallet’s database.

+

Inserts a [TxOut] at [OutPoint] into the wallet’s transaction graph.

+

This is used for providing a previous output’s value so that we can use calculate_fee +or calculate_fee_rate on a given transaction. Outputs inserted with this method will +not be returned in list_unspent or list_output.

+

Any inserted TxOuts are not persisted until commit is called.

+

WARNING: This should only be used to add TxOuts that the wallet does not own. Only +insert TxOuts that you trust the values for!

+

Calculates the fee of a given transaction. Returns 0 if tx is a coinbase transaction.

+

To calculate the fee for a [Transaction] with inputs not owned by this wallet you must +manually insert the TxOut(s) into the tx graph using the insert_txout function.

+

Note tx does not have to be in the graph for this to work.

+
Examples
+
let tx = wallet.get_tx(txid).expect("transaction").tx_node.tx;
+let fee = wallet.calculate_fee(&tx).expect("fee");
+ +
let tx = &psbt.clone().extract_tx().expect("tx");
+let fee = wallet.calculate_fee(tx).expect("fee");
+

Calculate the [FeeRate] for a given transaction.

+

To calculate the fee rate for a [Transaction] with inputs not owned by this wallet you must +manually insert the TxOut(s) into the tx graph using the insert_txout function.

+

Note tx does not have to be in the graph for this to work.

+
Examples
+
let tx = wallet.get_tx(txid).expect("transaction").tx_node.tx;
+let fee_rate = wallet.calculate_fee_rate(&tx).expect("fee rate");
+ +
let tx = &psbt.clone().extract_tx().expect("tx");
+let fee_rate = wallet.calculate_fee_rate(tx).expect("fee rate");
+

Compute the tx’s sent and received [Amount]s.

+

This method returns a tuple (sent, received). Sent is the sum of the txin amounts +that spend from previous txouts tracked by this wallet. Received is the summation +of this tx’s outputs that send to script pubkeys tracked by this wallet.

+
Examples
+
let tx = wallet.get_tx(txid).expect("tx exists").tx_node.tx;
+let (sent, received) = wallet.sent_and_received(&tx);
+ +
let tx = &psbt.clone().extract_tx().expect("tx");
+let (sent, received) = wallet.sent_and_received(tx);
+

Get a single transaction from the wallet as a [CanonicalTx] (if the transaction exists).

+

CanonicalTx contains the full transaction alongside meta-data such as:

+
    +
  • Blocks that the transaction is Anchored in. These may or may not be blocks that exist +in the best chain.
  • +
  • The [ChainPosition] of the transaction in the best chain - whether the transaction is +confirmed or unconfirmed. If the transaction is confirmed, the anchor which proves the +confirmation is provided. If the transaction is unconfirmed, the unix timestamp of when +the transaction was last seen in the mempool is provided.
  • +
+ +
use bdk_chain::Anchor;
+use bdk_wallet::{chain::ChainPosition, Wallet};
+
+let canonical_tx = wallet.get_tx(my_txid).expect("panic if tx does not exist");
+
+// get reference to full transaction
+println!("my tx: {:#?}", canonical_tx.tx_node.tx);
+
+// list all transaction anchors
+for anchor in canonical_tx.tx_node.anchors {
+    println!(
+        "tx is anchored by block of hash {}",
+        anchor.anchor_block().hash
+    );
+}
+
+// get confirmation status of transaction
+match canonical_tx.chain_position {
+    ChainPosition::Confirmed(anchor) => println!(
+        "tx is confirmed at height {}, we know this since {}:{} is in the best chain",
+        anchor.confirmation_height, anchor.anchor_block.height, anchor.anchor_block.hash,
+    ),
+    ChainPosition::Unconfirmed(last_seen) => println!(
+        "tx is last seen at {}, it is unconfirmed as it is not anchored in the best chain",
+        last_seen,
+    ),
+}
+

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.

+

Returns whether anything changed with the transaction insertion (e.g. false if the +transaction was already inserted at the same position).

+

A tx can be rejected if position has a height greater than the latest_checkpoint. +Therefore you should use insert_checkpoint to insert new checkpoints before manually +inserting new transactions.

+

WARNING: If position is confirmed, we anchor the tx to a the lowest checkpoint that +is >= the position’s height. The caller is responsible for ensuring the tx exists in our +local view of the best chain’s history.

+

Iterate over the transactions in the wallet.

+

Return the balance, separated into available, trusted-pending, untrusted-pending and immature +values.

+

Add an external signer

+

See the signer module for an example.

+

Get the signers

+
Example
+
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.

+

This returns a blank TxBuilder from which you can specify the parameters for the transaction.

+
Example
+
let psbt = {
+   let mut builder =  wallet.build_tx();
+   builder
+       .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
+   builder.finish()?
+};
+
+// sign and broadcast ...
+

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.

+
Example
+
let mut psbt = {
+    let mut builder = wallet.build_tx();
+    builder
+        .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
+        .enable_rbf();
+    builder.finish()?
+};
+let _ = wallet.sign(&mut psbt, SignOptions::default())?;
+let tx = psbt.clone().extract_tx().expect("tx");
+// broadcast tx but it's taking too long to confirm so we want to bump the fee
+let mut psbt =  {
+    let mut builder = wallet.build_fee_bump(tx.txid())?;
+    builder
+        .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"));
+    builder.finish()?
+};
+
+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 +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 +signers will follow the options, but the “software signers” (WIF keys and xprv) defined +in this library will.

+
Example
+
let mut psbt = {
+    let mut builder = wallet.build_tx();
+    builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
+    builder.finish()?
+};
+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 +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 +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.

+

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

+

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 currently staged changed to the persistence backend returning and error when +this fails.

+

This returns whether the update resulted in any changes.

+

Returns the changes that will be committed with the next call to commit.

+

Get a reference to the inner [TxGraph].

+

Get a reference to the inner [KeychainTxOutIndex].

+

Get a reference to the inner [LocalChain].

+

Introduces a block of height to the wallet, and tries to connect it to the +prev_blockhash of the block’s header.

+

This is a convenience method that is equivalent to calling apply_block_connected_to +with prev_blockhash and height-1 as the connected_to parameter.

+

Applies relevant transactions from block of height to the wallet, and connects the +block to the internal chain.

+

The connected_to parameter informs the wallet how this block connects to the internal +[LocalChain]. Relevant transactions are filtered from the block and inserted into the +internal [TxGraph].

+

Apply relevant unconfirmed transactions to the wallet.

+

Transactions that are not relevant are filtered out.

+

This method takes in an iterator of (tx, last_seen) where last_seen is the timestamp of +when the transaction was last seen in the mempool. This is used for conflict resolution +when there is conflicting unconfirmed transactions. The transaction with the later +last_seen is prioritized.

+

Methods to construct sync/full-scan requests for spk-based chain sources.

+

Create a partial [SyncRequest] for this wallet for all revealed spks.

+

This is the first step when performing a spk-based wallet partial sync, the returned +[SyncRequest] collects all revealed script pubkeys from the wallet keychain needed to +start a blockchain sync with a spk based blockchain client.

+

Create a [`FullScanRequest] for this wallet.

+

This is the first step when performing a spk-based wallet full scan, the returned +[`FullScanRequest] collects iterators for the wallet’s keychain script pub keys needed to +start a blockchain full scan with a spk based blockchain client.

+

This operation is generally only used when importing or restoring a previously used wallet +in which the list of used scripts is not known.

+

Trait Implementations§

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 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/wallet/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/trait.IsDust.html new file mode 100644 index 0000000000..fa47d50e51 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/trait.IsDust.html @@ -0,0 +1,8 @@ +IsDust in bdk_wallet::wallet - Rust

Trait bdk_wallet::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 +keep it compatible with network dust rate

+

Required Methods§

Check whether or not a value is below dust limit

+

Implementations on Foreign Types§

Implementors§

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.AddForeignUtxoError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.AddForeignUtxoError.html new file mode 100644 index 0000000000..9c1079e5e9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.AddForeignUtxoError.html @@ -0,0 +1,20 @@ +AddForeignUtxoError in bdk_wallet::wallet::tx_builder - Rust
pub enum AddForeignUtxoError {
+    InvalidTxid {
+        input_txid: Txid,
+        foreign_utxo: OutPoint,
+    },
+    InvalidOutpoint(OutPoint),
+    MissingUtxo,
+}
Expand description

Error returned from TxBuilder::add_foreign_utxo.

+

Variants§

§

InvalidTxid

Fields

§input_txid: Txid

PSBT input txid

+
§foreign_utxo: OutPoint

Foreign UTXO outpoint

+

Foreign utxo outpoint txid does not match PSBT input txid

+
§

InvalidOutpoint(OutPoint)

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

+
§

MissingUtxo

Foreign utxo missing witness_utxo or non_witness_utxo

+

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/wallet/tx_builder/enum.AddUtxoError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.AddUtxoError.html new file mode 100644 index 0000000000..71b8782ffb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.AddUtxoError.html @@ -0,0 +1,11 @@ +AddUtxoError in bdk_wallet::wallet::tx_builder - Rust
pub enum AddUtxoError {
+    UnknownUtxo(OutPoint),
+}
Expand description

Error returned from TxBuilder::add_utxo and TxBuilder::add_utxos

+

Variants§

§

UnknownUtxo(OutPoint)

Happens when trying to spend an UTXO that is not in the internal database

+

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/wallet/tx_builder/enum.AllowShrinkingError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.AllowShrinkingError.html new file mode 100644 index 0000000000..c370d58ef9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.AllowShrinkingError.html @@ -0,0 +1,11 @@ +AllowShrinkingError in bdk_wallet::wallet::tx_builder - Rust
pub enum AllowShrinkingError {
+    MissingScriptPubKey(ScriptBuf),
+}
Expand description

Error returned from TxBuilder::allow_shrinking

+

Variants§

§

MissingScriptPubKey(ScriptBuf)

Script/PubKey was not in the original transaction

+

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/wallet/tx_builder/enum.ChangeSpendPolicy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.ChangeSpendPolicy.html new file mode 100644 index 0000000000..3ab92f4649 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.ChangeSpendPolicy.html @@ -0,0 +1,18 @@ +ChangeSpendPolicy in bdk_wallet::wallet::tx_builder - Rust
pub enum ChangeSpendPolicy {
+    ChangeAllowed,
+    OnlyChange,
+    ChangeForbidden,
+}
Expand description

Policy regarding the use of change outputs when creating a transaction

+

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 +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
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/wallet/tx_builder/enum.TxOrdering.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.TxOrdering.html new file mode 100644 index 0000000000..8e86c588f4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/enum.TxOrdering.html @@ -0,0 +1,19 @@ +TxOrdering in bdk_wallet::wallet::tx_builder - Rust
pub enum TxOrdering {
+    Shuffle,
+    Untouched,
+    Bip69Lexicographic,
+}
Expand description

Ordering of the transaction’s inputs and outputs

+

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 +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
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/wallet/tx_builder/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/index.html new file mode 100644 index 0000000000..590df4f3f3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/index.html @@ -0,0 +1,18 @@ +bdk_wallet::wallet::tx_builder - Rust

Module bdk_wallet::wallet::tx_builder

source ·
Expand description

Transaction builder

+

Example

+
// create a TxBuilder from a wallet
+let mut tx_builder = wallet.build_tx();
+
+tx_builder
+    // Create a transaction with one output to `to_address` of 50_000 satoshi
+    .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
+    // With a custom fee rate of 5.0 satoshi/vbyte
+    .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
+    // Only spend non-change outputs
+    .do_not_spend_change()
+    // Turn on RBF signaling
+    .enable_rbf();
+let psbt = tx_builder.finish()?;
+

Structs

Marker type to indicate the TxBuilder is being used to bump the fee of an existing transaction.
Marker type to indicate the TxBuilder is being used to create a new transaction (as opposed +to bumping the fee of an existing one).
A transaction builder

Enums

Policy regarding the use of change outputs when creating a transaction
Ordering of the transaction’s inputs and outputs

Traits

Context in which the TxBuilder is valid
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/sidebar-items.js new file mode 100644 index 0000000000..abc3e92eca --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/sidebar-items.js @@ -0,0 +1 @@ +window.SIDEBAR_ITEMS = {"enum":[["AddForeignUtxoError","Error returned from [`TxBuilder::add_foreign_utxo`]."],["AddUtxoError","Error returned from [`TxBuilder::add_utxo`] and [`TxBuilder::add_utxos`]"],["AllowShrinkingError","Error returned from [`TxBuilder::allow_shrinking`]"],["ChangeSpendPolicy","Policy regarding the use of change outputs when creating a transaction"],["TxOrdering","Ordering of the transaction’s inputs and outputs"]],"struct":[["BumpFee","Marker type to indicate the [`TxBuilder`] is being used to bump the fee of an existing transaction."],["CreateTx","Marker type to indicate the [`TxBuilder`] is being used to create a new transaction (as opposed to bumping the fee of an existing one)."],["TxBuilder","A transaction builder"]],"trait":[["TxBuilderContext","Context in which the [`TxBuilder`] is valid"]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/struct.BumpFee.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/struct.BumpFee.html new file mode 100644 index 0000000000..69e745fa0e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/struct.BumpFee.html @@ -0,0 +1,7 @@ +BumpFee in bdk_wallet::wallet::tx_builder - Rust
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 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/wallet/tx_builder/struct.CreateTx.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/struct.CreateTx.html new file mode 100644 index 0000000000..77bbe78def --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/struct.CreateTx.html @@ -0,0 +1,8 @@ +CreateTx in bdk_wallet::wallet::tx_builder - Rust
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.

+

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_wallet/wallet/tx_builder/struct.TxBuilder.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/struct.TxBuilder.html new file mode 100644 index 0000000000..c4021e57a6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/struct.TxBuilder.html @@ -0,0 +1,244 @@ +TxBuilder in bdk_wallet::wallet::tx_builder - Rust
pub struct TxBuilder<'a, 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.

+

Each option setting method on TxBuilder takes and returns &mut self so you can chain calls +as in the following example:

+ +
// chaining
+let psbt1 = {
+    let mut builder = wallet.build_tx();
+    builder
+        .ordering(TxOrdering::Untouched)
+        .add_recipient(addr1.script_pubkey(), Amount::from_sat(50_000))
+        .add_recipient(addr2.script_pubkey(), Amount::from_sat(50_000));
+    builder.finish()?
+};
+
+// non-chaining
+let psbt2 = {
+    let mut builder = wallet.build_tx();
+    builder.ordering(TxOrdering::Untouched);
+    for addr in &[addr1, addr2] {
+        builder.add_recipient(addr.script_pubkey(), Amount::from_sat(50_000));
+    }
+    builder.finish()?
+};
+
+assert_eq!(psbt1.unsigned_tx.output[..2], psbt2.unsigned_tx.output[..2]);
+

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.

+

This method sets the mining fee paid by the transaction as a rate on its size. +This means that the total fee paid is equal to fee_rate times the size +of the transaction. Default is 1 sat/vB in accordance with Bitcoin Core’s default +relay policy.

+

Note that this is really a minimum feerate – it’s possible to +overshoot it slightly since adding a change output to drain the remaining +excess might not be viable.

+

Set an absolute fee +The fee_absolute method refers to the absolute transaction fee in satoshis (sats). +If anyone sets both the fee_absolute method and the fee_rate method, +the FeePolicy enum will be set by whichever method was called last, +as the FeeRate and FeeAmount are mutually exclusive.

+

Note that this is really a minimum absolute fee – it’s possible to +overshoot it slightly since adding a change output to drain the remaining +excess might not be viable.

+

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 +SatisfiableItem::Thresh::items).

+
Example
+

An example of when the policy path is needed is the following descriptor: +wsh(thresh(2,pk(A),sj:and_v(v:pk(B),n:older(6)),snj:and_v(v:pk(C),after(630000)))), +derived from the miniscript policy thresh(2,pk(A),and(pk(B),older(6)),and(pk(C),after(630000))). +It declares three descriptor fragments, and at the top level it uses thresh() to +ensure that at least two of them are satisfied. The individual fragments are:

+
    +
  1. pk(A)
  2. +
  3. and(pk(B),older(6))
  4. +
  5. and(pk(C),after(630000))
  6. +
+

When those conditions are combined in pairs, it’s clear that the transaction needs to be created +differently depending on how the user intends to satisfy the policy afterwards:

+
    +
  • If fragments 1 and 2 are used, the transaction will need to use a specific +n_sequence in order to spend an OP_CSV branch.
  • +
  • If fragments 1 and 3 are used, the transaction will need to use a specific locktime +in order to spend an OP_CLTV branch.
  • +
  • If fragments 2 and 3 are used, the transaction will need both.
  • +
+

When the spending policy is represented as a tree (see +Wallet::policies), every node +is assigned a unique identifier that can be used in the policy path to specify which of +the node’s children the user intends to satisfy: for instance, assuming the thresh() +root node of this example has an id of aabbccdd, the policy path map would look like:

+

{ "aabbccdd" => [0, 1] }

+

where the key is the node’s id, and the value is a list of the children that should be +used, in no particular order.

+

If a particularly complex descriptor has multiple ambiguous thresholds in its structure, +multiple entries can be added to the map, one for each node that requires an explicit path.

+ +
Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
+    .unwrap()
+    .assume_checked();
+let mut path = BTreeMap::new();
+path.insert("aabbccdd".to_string(), vec![0, 1]);
+
+let builder = wallet
+    .build_tx()
+    .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
+    .policy_path(path, KeychainKind::External);
+
+

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

+

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.

+

At a minimum to add a foreign UTXO we need:

+
    +
  1. outpoint: To add it to the raw transaction.
  2. +
  3. psbt_input: To know the value.
  4. +
  5. satisfaction_weight: To know how much weight/vbytes the input will add to the transaction for fee calculation.
  6. +
+

There are several security concerns about adding foreign UTXOs that application +developers should consider. First, how do you know the value of the input is correct? If a +non_witness_utxo is provided in the psbt_input then this method implicitly verifies the +value by checking it against the transaction. If only a witness_utxo is provided then this +method doesn’t verify the value but just takes it as a given – it is up to you to check +that whoever sent you the input_psbt was not lying!

+

Secondly, you must somehow provide satisfaction_weight of the input. Depending on your +application it may be important that this be known precisely. If not, a malicious +counterparty may fool you into putting in a value that is too low, giving the transaction a +lower than expected feerate. They could also fool you into putting a value that is too high +causing you to pay a fee that is too high. The party who is broadcasting the transaction can +of course check the real input weight matches the expected weight prior to broadcasting.

+

To guarantee the max_weight_to_satisfy is correct, you can require the party providing the +psbt_input provide a miniscript descriptor for the input so you can check it against the +script_pubkey and then ask it for the max_weight_to_satisfy.

+

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

+

In order to use Wallet::calculate_fee or Wallet::calculate_fee_rate for a transaction +created with foreign UTXO(s) you must manually insert the corresponding TxOut(s) into the tx +graph using the Wallet::insert_txout function.

+
Errors
+

This method returns errors in the following circumstances:

+
    +
  1. The psbt_input does not contain a witness_utxo or non_witness_utxo.
  2. +
  3. The data in non_witness_utxo does not match what is in outpoint.
  4. +
+

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.

+

Same as add_foreign_utxo but allows to set the nSequence value.

+

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

+

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

+

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

+

Use this option very carefully

+

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

+

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

+

This effectively adds all the change outputs to the “unspendable” list. See +TxBuilder::unspendable.

+

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 +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 +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 +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

+

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.

+

Enable signaling RBF

+

This will use the default nSequence value of 0xFFFFFFFD.

+

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.

+

This will be used to:

+
    +
  1. Set the nLockTime for preventing fee sniping. +Note: This will be ignored if you manually specify a nlocktime using TxBuilder::nlocktime.
  2. +
  3. Decide whether coinbase outputs are mature or not. If the coinbase outputs are not +mature at current_height, we ignore them in the coin selection. +If you want to create a transaction that spends immature coinbase inputs, manually +add them using TxBuilder::add_utxos.
  4. +
+

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.

+

Note: by avoiding a dust limit check you may end up with a transaction that is non-standard.

+

Finish building the transaction.

+

Returns a new [Psbt] per BIP174.

+

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 +coins are too small) it will not be included in the resulting transaction. The only +difference is that it is valid to use drain_to without setting any ordinary recipients +with add_recipient (but it is perfectly fine to add recipients as well).

+

If you choose not to set any recipients, you should either provide the utxos that the +transaction should spend via add_utxos, or set drain_wallet to spend all of them.

+

When bumping the fees of a transaction made with this option, you probably want to +use allow_shrinking to allow this output to be reduced to pay for the extra fees.

+
Example
+

drain_to is very useful for draining all the coins in a wallet with drain_wallet to a +single address.

+ +
Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
+    .unwrap()
+    .assume_checked();
+let mut tx_builder = wallet.build_tx();
+
+tx_builder
+    // Spend all outputs in this wallet.
+    .drain_wallet()
+    // Send the excess (which is all the coins minus the fee) to this address.
+    .drain_to(to_address.script_pubkey())
+    .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
+    .enable_rbf();
+let psbt = tx_builder.finish()?;
+

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 +preserved then it is currently not guaranteed to be in the same position as it was +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.

+

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_wallet/wallet/tx_builder/trait.TxBuilderContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/trait.TxBuilderContext.html new file mode 100644 index 0000000000..94acc722f1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/tx_builder/trait.TxBuilderContext.html @@ -0,0 +1,3 @@ +TxBuilderContext in bdk_wallet::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/wallet/utils/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/utils/trait.IsDust.html new file mode 100644 index 0000000000..47426536de --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk_wallet/wallet/utils/trait.IsDust.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../bdk_wallet/wallet/trait.IsDust.html...

+ + + \ 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 569cd08f2f..98748871e4 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","bdk_bitcoind_rpc","bdk_chain","bdk_coin_select","bdk_electrum","bdk_esplora","bdk_file_store","bdk_hwi","bdk_persist","bdk_testenv","bdk_tmp_plan","example_bitcoind_rpc_polling","example_cli","example_electrum","example_esplora","wallet_electrum_example","wallet_esplora_async","wallet_esplora_blocking","wallet_rpc"]; \ No newline at end of file +window.ALL_CRATES = ["bdk_bitcoind_rpc","bdk_chain","bdk_coin_select","bdk_electrum","bdk_esplora","bdk_file_store","bdk_hwi","bdk_persist","bdk_testenv","bdk_tmp_plan","bdk_wallet","example_bitcoind_rpc_polling","example_cli","example_electrum","example_esplora","wallet_electrum_example","wallet_esplora_async","wallet_esplora_blocking","wallet_rpc"]; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_bitcoind_rpc_polling/type.ChangeSet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_bitcoind_rpc_polling/type.ChangeSet.html index 93c49240ed..74f57a74be 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_bitcoind_rpc_polling/type.ChangeSet.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_bitcoind_rpc_polling/type.ChangeSet.html @@ -1 +1 @@ -ChangeSet in example_bitcoind_rpc_polling - Rust
\ No newline at end of file +ChangeSet in example_bitcoind_rpc_polling - Rust

Type Definition example_bitcoind_rpc_polling::ChangeSet

source ·
pub(crate) type ChangeSet = (ChangeSet, ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<Keychain>>);
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.create_tx.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.create_tx.html index 4649b94070..11d5e63c1e 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.create_tx.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.create_tx.html @@ -1 +1 @@ -create_tx in example_cli - Rust

Function example_cli::create_tx

source ·
pub fn create_tx<A: Anchor, O: ChainOracle>(
    graph: &mut KeychainTxGraph<A>,
    chain: &O,
    keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
    cs_algorithm: CoinSelectionAlgo,
    address: Address,
    value: u64
) -> Result<(Transaction, Option<CreateTxChange>)>where
    O::Error: Error + Send + Sync + 'static,
\ No newline at end of file +create_tx in example_cli - Rust

Function example_cli::create_tx

source ·
pub fn create_tx<A: Anchor, O: ChainOracle>(
    graph: &mut KeychainTxGraph<A>,
    chain: &O,
    keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
    cs_algorithm: CoinSelectionAlgo,
    address: Address,
    value: u64
) -> Result<(Transaction, Option<CreateTxChange>)>where
    O::Error: Error + Send + Sync + 'static,
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.handle_commands.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.handle_commands.html index 4f276f4c26..98828ccd4d 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.handle_commands.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.handle_commands.html @@ -1 +1 @@ -handle_commands in example_cli - Rust

Function example_cli::handle_commands

source ·
pub fn handle_commands<CS: Subcommand, S: Args, A: Anchor, O: ChainOracle, C>(
    graph: &Mutex<KeychainTxGraph<A>>,
    db: &Mutex<Persist<C>>,
    chain: &Mutex<O>,
    keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
    network: Network,
    broadcast: impl FnOnce(S, &Transaction) -> Result<()>,
    cmd: Commands<CS, S>
) -> Result<()>where
    O::Error: Error + Send + Sync + 'static,
    C: Default + Append + DeserializeOwned + Serialize + From<KeychainChangeSet<A>>,
\ No newline at end of file +handle_commands in example_cli - Rust

Function example_cli::handle_commands

source ·
pub fn handle_commands<CS: Subcommand, S: Args, A: Anchor, O: ChainOracle, C>(
    graph: &Mutex<KeychainTxGraph<A>>,
    db: &Mutex<Persist<C>>,
    chain: &Mutex<O>,
    keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
    network: Network,
    broadcast: impl FnOnce(S, &Transaction) -> Result<()>,
    cmd: Commands<CS, S>
) -> Result<()>where
    O::Error: Error + Send + Sync + 'static,
    C: Default + Append + DeserializeOwned + Serialize + From<KeychainChangeSet<A>>,
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.init.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.init.html index 695a818526..f8b1c714fa 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.init.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.init.html @@ -1,3 +1,3 @@ -init in example_cli - Rust

Function example_cli::init

source ·
pub fn init<CS: Subcommand, S: Args, C>(
    db_magic: &[u8],
    db_default_path: &str
) -> Result<Init<CS, S, C>>where
    C: Default + Append + Serialize + DeserializeOwned + Send + Sync + 'static,
Expand description

Parses command line arguments and initializes all components, creating +init in example_cli - Rust

Function example_cli::init

source ·
pub fn init<CS: Subcommand, S: Args, C>(
    db_magic: &[u8],
    db_default_path: &str
) -> Result<Init<CS, S, C>>where
    C: Default + Append + Serialize + DeserializeOwned + Send + Sync + 'static,
Expand description

Parses command line arguments and initializes all components, creating a file store with the given parameters, or loading one if it exists.

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.planned_utxos.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.planned_utxos.html index a6a5a5e716..5c548ed910 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.planned_utxos.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/fn.planned_utxos.html @@ -1 +1 @@ -planned_utxos in example_cli - Rust

Function example_cli::planned_utxos

source ·
pub fn planned_utxos<A: Anchor, O: ChainOracle, K: Clone + CanDerive>(
    graph: &KeychainTxGraph<A>,
    chain: &O,
    assets: &Assets<K>
) -> Result<Vec<PlannedUtxo<K, A>>, O::Error>
\ No newline at end of file +planned_utxos in example_cli - Rust

Function example_cli::planned_utxos

source ·
pub fn planned_utxos<A: Anchor, O: ChainOracle, K: Clone + CanDerive>(
    graph: &KeychainTxGraph<A>,
    chain: &O,
    assets: &Assets<K>
) -> Result<Vec<PlannedUtxo<K, A>>, O::Error>
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/struct.CreateTxChange.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/struct.CreateTxChange.html index 0d5bfa7f3d..4577b173ca 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/struct.CreateTxChange.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/struct.CreateTxChange.html @@ -1,8 +1,8 @@ CreateTxChange in example_cli - Rust
pub struct CreateTxChange {
-    pub index_changeset: ChangeSet<Keychain>,
+    pub index_changeset: ChangeSet<Keychain>,
     pub change_keychain: Keychain,
     pub index: u32,
-}

Fields§

§index_changeset: ChangeSet<Keychain>§change_keychain: Keychain§index: u32

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.

+}

Fields§

§index_changeset: ChangeSet<Keychain>§change_keychain: Keychain§index: u32

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.

diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/struct.Init.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/struct.Init.html index f0b9568fa2..6077f6a4b9 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/struct.Init.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/struct.Init.html @@ -1,13 +1,13 @@ Init in example_cli - Rust

Struct example_cli::Init

source ·
pub struct Init<CS: Subcommand, S: Args, C> {
     pub args: Args<CS, S>,
     pub keymap: KeyMap,
-    pub index: KeychainTxOutIndex<Keychain>,
+    pub index: KeychainTxOutIndex<Keychain>,
     pub db: Mutex<Persist<C>>,
     pub init_changeset: C,
 }
Expand description

The initial state returned by init.

Fields§

§args: Args<CS, S>

Arguments parsed by the cli.

§keymap: KeyMap

Descriptor keymap.

-
§index: KeychainTxOutIndex<Keychain>

Keychain-txout index.

+
§index: KeychainTxOutIndex<Keychain>

Keychain-txout index.

§db: Mutex<Persist<C>>

Persistence backend.

§init_changeset: C

Initial changeset.

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.

diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.KeychainChangeSet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.KeychainChangeSet.html index 7f3f8999d1..3aebd69f52 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.KeychainChangeSet.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.KeychainChangeSet.html @@ -1 +1 @@ -KeychainChangeSet in example_cli - Rust

Type Definition example_cli::KeychainChangeSet

source ·
pub type KeychainChangeSet<A> = (ChangeSet, ChangeSet<A, ChangeSet<Keychain>>);
\ No newline at end of file +KeychainChangeSet in example_cli - Rust

Type Definition example_cli::KeychainChangeSet

source ·
pub type KeychainChangeSet<A> = (ChangeSet, ChangeSet<A, ChangeSet<Keychain>>);
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.KeychainTxGraph.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.KeychainTxGraph.html index e96eeba1f2..cf02df9814 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.KeychainTxGraph.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.KeychainTxGraph.html @@ -1 +1 @@ -KeychainTxGraph in example_cli - Rust

Type Definition example_cli::KeychainTxGraph

source ·
pub type KeychainTxGraph<A> = IndexedTxGraph<A, KeychainTxOutIndex<Keychain>>;
\ No newline at end of file +KeychainTxGraph in example_cli - Rust

Type Definition example_cli::KeychainTxGraph

source ·
pub type KeychainTxGraph<A> = IndexedTxGraph<A, KeychainTxOutIndex<Keychain>>;
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.PlannedUtxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.PlannedUtxo.html index 120288d032..a7b272a55e 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.PlannedUtxo.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_cli/type.PlannedUtxo.html @@ -1 +1 @@ -PlannedUtxo in example_cli - Rust

Type Definition example_cli::PlannedUtxo

source ·
pub type PlannedUtxo<K, A> = (Plan<K>, FullTxOut<A>);
\ No newline at end of file +PlannedUtxo in example_cli - Rust

Type Definition example_cli::PlannedUtxo

source ·
pub type PlannedUtxo<K, A> = (Plan<K>, FullTxOut<A>);
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_electrum/type.ChangeSet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_electrum/type.ChangeSet.html index d8054c7936..11dfa4ddee 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_electrum/type.ChangeSet.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_electrum/type.ChangeSet.html @@ -1 +1 @@ -ChangeSet in example_electrum - Rust

Type Definition example_electrum::ChangeSet

source ·
\ No newline at end of file +ChangeSet in example_electrum - Rust

Type Definition example_electrum::ChangeSet

source ·
pub(crate) type ChangeSet = (ChangeSet, ChangeSet<ConfirmationHeightAnchor, ChangeSet<Keychain>>);
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_esplora/type.ChangeSet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_esplora/type.ChangeSet.html index e99a895001..6e45f6925b 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_esplora/type.ChangeSet.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/example_esplora/type.ChangeSet.html @@ -1 +1 @@ -ChangeSet in example_esplora - Rust

Type Definition example_esplora::ChangeSet

source ·
\ No newline at end of file +ChangeSet in example_esplora - Rust

Type Definition example_esplora::ChangeSet

source ·
pub(crate) type ChangeSet = (ChangeSet, ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<Keychain>>);
\ 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 01a55467d8..93fcd70225 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/help.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/help.html @@ -1 +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/descriptor/template/trait.DescriptorTemplate.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/template/trait.DescriptorTemplate.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/descriptor/trait.ExtractPolicy.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.ExtractPolicy.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.ExtractPolicy.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/descriptor/trait.IntoWalletDescriptor.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.IntoWalletDescriptor.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.IntoWalletDescriptor.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/keys/trait.DerivableKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.DerivableKey.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.DerivableKey.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/keys/trait.ExtScriptContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ExtScriptContext.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ExtScriptContext.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/keys/trait.GeneratableDefaultOptions.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableDefaultOptions.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableDefaultOptions.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/keys/trait.GeneratableKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableKey.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableKey.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/keys/trait.IntoDescriptorKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.IntoDescriptorKey.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.IntoDescriptorKey.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/psbt/trait.PsbtUtils.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/psbt/trait.PsbtUtils.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/psbt/trait.PsbtUtils.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/wallet/coin_selection/trait.CoinSelectionAlgorithm.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.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/wallet/signer/trait.InputSigner.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.InputSigner.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.InputSigner.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/wallet/signer/trait.SignerCommon.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.SignerCommon.js deleted file mode 100644 index fb042c4512..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.SignerCommon.js +++ /dev/null @@ -1,4 +0,0 @@ -(function() {var implementors = { -"bdk":[], -"bdk_hwi":[["impl SignerCommon for HWISigner"]] -};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/wallet/signer/trait.TransactionSigner.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.TransactionSigner.js deleted file mode 100644 index 68919d45f8..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.TransactionSigner.js +++ /dev/null @@ -1,4 +0,0 @@ -(function() {var implementors = { -"bdk":[], -"bdk_hwi":[["impl TransactionSigner for HWISigner"]] -};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/wallet/tx_builder/trait.TxBuilderContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.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/wallet/utils/trait.IsDust.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/utils/trait.IsDust.js deleted file mode 100644 index bb0690bde5..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/utils/trait.IsDust.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/tx_data_traits/trait.Append.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.Append.js index 7b3d82a242..ab2ab07e2d 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.Append.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.Append.js @@ -1,4 +1,4 @@ (function() {var implementors = { -"bdk":[["impl Append for ChangeSet"]], -"bdk_chain":[] +"bdk_chain":[], +"bdk_wallet":[["impl Append for ChangeSet"]] };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_persist/persist/trait.PersistBackend.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_persist/persist/trait.PersistBackend.js index bd9b0724ba..74f314ccf8 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_persist/persist/trait.PersistBackend.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_persist/persist/trait.PersistBackend.js @@ -1,4 +1,4 @@ (function() {var implementors = { -"bdk_file_store":[["impl<C> PersistBackend<C> for Store<C>where
    C: Append + Serialize + DeserializeOwned + Send + Sync,
"]], +"bdk_file_store":[["impl<C> PersistBackend<C> for Store<C>where
    C: Append + Serialize + DeserializeOwned + Send + Sync,
"]], "bdk_persist":[] };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_wallet/descriptor/template/trait.DescriptorTemplate.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/descriptor/template/trait.DescriptorTemplate.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/descriptor/template/trait.DescriptorTemplate.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/descriptor/trait.ExtractPolicy.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/descriptor/trait.ExtractPolicy.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/descriptor/trait.ExtractPolicy.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/descriptor/trait.IntoWalletDescriptor.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/descriptor/trait.IntoWalletDescriptor.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/descriptor/trait.IntoWalletDescriptor.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/keys/trait.DerivableKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.DerivableKey.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.DerivableKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/keys/trait.ExtScriptContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.ExtScriptContext.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.ExtScriptContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/keys/trait.GeneratableDefaultOptions.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.GeneratableDefaultOptions.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.GeneratableDefaultOptions.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/keys/trait.GeneratableKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.GeneratableKey.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.GeneratableKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/keys/trait.IntoDescriptorKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.IntoDescriptorKey.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/keys/trait.IntoDescriptorKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/psbt/trait.PsbtUtils.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/psbt/trait.PsbtUtils.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/psbt/trait.PsbtUtils.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/wallet/coin_selection/trait.CoinSelectionAlgorithm.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/coin_selection/trait.CoinSelectionAlgorithm.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/coin_selection/trait.CoinSelectionAlgorithm.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/wallet/signer/trait.InputSigner.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/signer/trait.InputSigner.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/signer/trait.InputSigner.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/wallet/signer/trait.SignerCommon.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/signer/trait.SignerCommon.js new file mode 100644 index 0000000000..e2be123c6f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/signer/trait.SignerCommon.js @@ -0,0 +1,4 @@ +(function() {var implementors = { +"bdk_hwi":[["impl SignerCommon for HWISigner"]], +"bdk_wallet":[] +};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_wallet/wallet/signer/trait.TransactionSigner.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/signer/trait.TransactionSigner.js new file mode 100644 index 0000000000..54cf1ae9be --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/signer/trait.TransactionSigner.js @@ -0,0 +1,4 @@ +(function() {var implementors = { +"bdk_hwi":[["impl TransactionSigner for HWISigner"]], +"bdk_wallet":[] +};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_wallet/wallet/tx_builder/trait.TxBuilderContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/tx_builder/trait.TxBuilderContext.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/tx_builder/trait.TxBuilderContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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_wallet/wallet/utils/trait.IsDust.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/utils/trait.IsDust.js new file mode 100644 index 0000000000..e69e7865df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk_wallet/wallet/utils/trait.IsDust.js @@ -0,0 +1,3 @@ +(function() {var implementors = { +"bdk_wallet":[] +};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 ff7fbd518a..5ffd443913 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,8 +1,8 @@ (function() {var implementors = { -"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 LocalOutput"],["impl Clone for WeightedUtxo"],["impl Clone for Utxo"],["impl Clone for LargestFirstCoinSelection"],["impl Clone for OldestFirstCoinSelection"],["impl Clone for BranchAndBoundCoinSelection"],["impl Clone for SignerId"],["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> Clone for TxBuilder<'a, Cs, Ctx>"],["impl Clone for TxOrdering"],["impl Clone for ChangeSpendPolicy"],["impl Clone for MiniscriptPsbtError"],["impl Clone for Update"],["impl Clone for ChangeSet"]], "bdk_chain":[["impl<I: Clone> Clone for SpkTxOutIndex<I>"],["impl<A: Clone> Clone for ChainPosition<A>"],["impl Clone for ConfirmationTime"],["impl Clone for BlockId"],["impl Clone for ConfirmationHeightAnchor"],["impl Clone for ConfirmationTimeHeightAnchor"],["impl<A: Clone> Clone for FullTxOut<A>"],["impl<A: Clone, IA: Clone> Clone for ChangeSet<A, IA>"],["impl<K: Clone> Clone for ChangeSet<K>"],["impl<K: Clone> Clone for KeychainTxOutIndex<K>"],["impl Clone for Balance"],["impl Clone for CheckPoint"],["impl Clone for LocalChain"],["impl Clone for MissingGenesisError"],["impl Clone for AlterCheckPointError"],["impl Clone for CannotConnectError"],["impl Clone for ApplyHeaderError"],["impl<A: Clone> Clone for TxGraph<A>"],["impl<'a, T: Clone, A: Clone> Clone for TxNode<'a, T, A>"],["impl<'a, T: Clone, A: Clone> Clone for CanonicalTx<'a, T, A>"],["impl<A: Clone> Clone for ChangeSet<A>"],["impl Clone for DescriptorId"],["impl<D: Clone> Clone for SpkIterator<D>"]], "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>"]], +"bdk_wallet":[["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 LocalOutput"],["impl Clone for WeightedUtxo"],["impl Clone for Utxo"],["impl Clone for LargestFirstCoinSelection"],["impl Clone for OldestFirstCoinSelection"],["impl Clone for BranchAndBoundCoinSelection"],["impl Clone for SignerId"],["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> Clone for TxBuilder<'a, Cs, Ctx>"],["impl Clone for TxOrdering"],["impl Clone for ChangeSpendPolicy"],["impl Clone for MiniscriptPsbtError"],["impl Clone for Update"],["impl Clone for ChangeSet"]], "example_bitcoind_rpc_polling":[["impl Clone for RpcArgs"],["impl Clone for RpcCommands"]], "example_cli":[["impl<CS: Clone + Subcommand, S: Clone + Args> Clone for Commands<CS, S>"],["impl Clone for CoinSelectionAlgo"],["impl Clone for AddressCmd"],["impl Clone for TxOutCmd"],["impl Clone for Keychain"]], "example_electrum":[["impl Clone for ElectrumCommands"],["impl Clone for ElectrumArgs"],["impl Clone for ScanOptions"]], 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 92840f6f30..adfdb5aaf4 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,6 +1,6 @@ (function() {var implementors = { -"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 LocalOutput"],["impl Eq for WeightedUtxo"],["impl Eq for Utxo"],["impl Eq for SignerId"],["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<A: Eq> Eq for ChainPosition<A>"],["impl Eq for ConfirmationTime"],["impl Eq for BlockId"],["impl Eq for ConfirmationHeightAnchor"],["impl Eq for ConfirmationTimeHeightAnchor"],["impl<A: Eq> Eq for FullTxOut<A>"],["impl Eq for Balance"],["impl<'a, T: Eq, A: Eq> Eq for TxNode<'a, T, A>"],["impl<'a, T: Eq, A: Eq> Eq for CanonicalTx<'a, T, A>"],["impl Eq for CalculateFeeError"],["impl Eq for DescriptorId"]], "bdk_coin_select":[["impl Eq for SelectionConstraint"],["impl Eq for ExcessStrategyKind"]], +"bdk_wallet":[["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 LocalOutput"],["impl Eq for WeightedUtxo"],["impl Eq for Utxo"],["impl Eq for SignerId"],["impl Eq for SignerContext"],["impl Eq for SignerOrdering"],["impl Eq for TapLeavesOptions"],["impl Eq for TxOrdering"],["impl Eq for ChangeSpendPolicy"],["impl Eq for AddressInfo"]], "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 1cd41834c1..0806c79b5c 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,6 +1,6 @@ (function() {var implementors = { -"bdk":[["impl Ord for KeychainKind"],["impl Ord for SignerId"],["impl Ord for SignerOrdering"],["impl Ord for TxOrdering"],["impl Ord for ChangeSpendPolicy"]], "bdk_chain":[["impl<A: Ord> Ord for ChainPosition<A>"],["impl Ord for ConfirmationTime"],["impl Ord for BlockId"],["impl Ord for ConfirmationHeightAnchor"],["impl Ord for ConfirmationTimeHeightAnchor"],["impl<A: Ord> Ord for FullTxOut<A>"],["impl<'a, T: Ord, A: Ord> Ord for TxNode<'a, T, A>"],["impl<'a, T: Ord, A: Ord> Ord for CanonicalTx<'a, T, A>"],["impl Ord for DescriptorId"]], "bdk_coin_select":[["impl Ord for ExcessStrategyKind"]], +"bdk_wallet":[["impl Ord for KeychainKind"],["impl Ord for SignerId"],["impl Ord for SignerOrdering"],["impl Ord for TxOrdering"],["impl Ord for ChangeSpendPolicy"]], "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 cfbae58f66..512177f03f 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,7 +1,7 @@ (function() {var implementors = { -"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<LocalOutput> for LocalOutput"],["impl PartialEq<WeightedUtxo> for WeightedUtxo"],["impl PartialEq<Utxo> for Utxo"],["impl PartialEq<SignerId> for SignerId"],["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<ChangeSet> for ChangeSet"],["impl PartialEq<AddressInfo> for AddressInfo"]], "bdk_chain":[["impl<A: PartialEq> PartialEq<ChainPosition<A>> for ChainPosition<A>"],["impl PartialEq<ConfirmationTime> for ConfirmationTime"],["impl PartialEq<BlockId> for BlockId"],["impl PartialEq<ConfirmationHeightAnchor> for ConfirmationHeightAnchor"],["impl PartialEq<ConfirmationTimeHeightAnchor> for ConfirmationTimeHeightAnchor"],["impl<A: PartialEq> PartialEq<FullTxOut<A>> for FullTxOut<A>"],["impl<A: PartialEq, IA: PartialEq> PartialEq<ChangeSet<A, IA>> for ChangeSet<A, IA>"],["impl<K: PartialEq> PartialEq<ChangeSet<K>> for ChangeSet<K>"],["impl PartialEq<Balance> for Balance"],["impl PartialEq<CheckPoint> for CheckPoint"],["impl PartialEq<LocalChain> for LocalChain"],["impl PartialEq<MissingGenesisError> for MissingGenesisError"],["impl PartialEq<AlterCheckPointError> for AlterCheckPointError"],["impl PartialEq<CannotConnectError> for CannotConnectError"],["impl PartialEq<ApplyHeaderError> for ApplyHeaderError"],["impl<A: PartialEq> PartialEq<TxGraph<A>> for TxGraph<A>"],["impl<'a, T: PartialEq, A: PartialEq> PartialEq<TxNode<'a, T, A>> for TxNode<'a, T, A>"],["impl<'a, T: PartialEq, A: PartialEq> PartialEq<CanonicalTx<'a, T, A>> for CanonicalTx<'a, T, A>"],["impl PartialEq<CalculateFeeError> for CalculateFeeError"],["impl<A: PartialEq> PartialEq<ChangeSet<A>> for ChangeSet<A>"],["impl PartialEq<DescriptorId> for DescriptorId"]], "bdk_coin_select":[["impl PartialEq<SelectionConstraint> for SelectionConstraint"],["impl PartialEq<ExcessStrategyKind> for ExcessStrategyKind"]], +"bdk_wallet":[["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<LocalOutput> for LocalOutput"],["impl PartialEq<WeightedUtxo> for WeightedUtxo"],["impl PartialEq<Utxo> for Utxo"],["impl PartialEq<SignerId> for SignerId"],["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<ChangeSet> for ChangeSet"],["impl PartialEq<AddressInfo> for AddressInfo"]], "example_cli":[["impl PartialEq<Keychain> for Keychain"]], "example_electrum":[["impl PartialEq<ScanOptions> for ScanOptions"]], "example_esplora":[["impl PartialEq<ScanOptions> for ScanOptions"]] 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 df841417fd..68a8e1d3b4 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,6 +1,6 @@ (function() {var implementors = { -"bdk":[["impl PartialOrd<Condition> for Condition"],["impl PartialOrd<KeychainKind> for KeychainKind"],["impl PartialOrd<SignerId> for SignerId"],["impl PartialOrd<SignerOrdering> for SignerOrdering"],["impl PartialOrd<TxOrdering> for TxOrdering"],["impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy"]], "bdk_chain":[["impl<A: PartialOrd> PartialOrd<ChainPosition<A>> for ChainPosition<A>"],["impl PartialOrd<ConfirmationTime> for ConfirmationTime"],["impl PartialOrd<BlockId> for BlockId"],["impl PartialOrd<ConfirmationHeightAnchor> for ConfirmationHeightAnchor"],["impl PartialOrd<ConfirmationTimeHeightAnchor> for ConfirmationTimeHeightAnchor"],["impl<A: PartialOrd> PartialOrd<FullTxOut<A>> for FullTxOut<A>"],["impl<'a, T: PartialOrd, A: PartialOrd> PartialOrd<TxNode<'a, T, A>> for TxNode<'a, T, A>"],["impl<'a, T: PartialOrd, A: PartialOrd> PartialOrd<CanonicalTx<'a, T, A>> for CanonicalTx<'a, T, A>"],["impl PartialOrd<DescriptorId> for DescriptorId"]], "bdk_coin_select":[["impl PartialOrd<ExcessStrategyKind> for ExcessStrategyKind"]], +"bdk_wallet":[["impl PartialOrd<Condition> for Condition"],["impl PartialOrd<KeychainKind> for KeychainKind"],["impl PartialOrd<SignerId> for SignerId"],["impl PartialOrd<SignerOrdering> for SignerOrdering"],["impl PartialOrd<TxOrdering> for TxOrdering"],["impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy"]], "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 7d79a4b9b4..9fd9945753 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,4 +1,4 @@ (function() {var implementors = { -"bdk":[["impl AsRef<[u8]> for KeychainKind"],["impl AsRef<TxGraph<ConfirmationTimeHeightAnchor>> for Wallet"]], -"bdk_chain":[["impl<A> AsRef<TxGraph<A>> for TxGraph<A>"],["impl AsRef<[u8]> for DescriptorId"],["impl AsRef<[u8; 32]> for DescriptorId"]] +"bdk_chain":[["impl<A> AsRef<TxGraph<A>> for TxGraph<A>"],["impl AsRef<[u8]> for DescriptorId"],["impl AsRef<[u8; 32]> for DescriptorId"]], +"bdk_wallet":[["impl AsRef<[u8]> for KeychainKind"],["impl AsRef<TxGraph<ConfirmationTimeHeightAnchor>> for Wallet"]] };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 5782a1e49c..16810245b6 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,8 +1,8 @@ (function() {var implementors = { -"bdk":[["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<HexToBytesError> for Error"],["impl From<PolicyError> for Error"],["impl From<bool> for Satisfaction"],["impl From<SatisfiableItem> for Policy"],["impl<Ctx: ScriptContext> From<Xpub> for ExtendedKey<Ctx>"],["impl<Ctx: ScriptContext> From<Xpriv> 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 CreateTxError"],["impl From<PolicyError> for CreateTxError"],["impl From<MiniscriptPsbtError> for CreateTxError"],["impl From<Error> for CreateTxError"],["impl From<Error> for CreateTxError"],["impl From<FullScanResult<KeychainKind, ConfirmationTimeHeightAnchor>> for Update"],["impl From<SyncResult<ConfirmationTimeHeightAnchor>> for Update"],["impl From<BTreeMap<u32, Option<BlockHash>, Global>> for ChangeSet"],["impl From<ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>> for ChangeSet"]], "bdk_chain":[["impl From<ChainPosition<ConfirmationTimeHeightAnchor>> for ConfirmationTime"],["impl From<(u32, BlockHash)> for BlockId"],["impl From<BlockId> for (u32, BlockHash)"],["impl From<(&u32, &BlockHash)> for BlockId"],["impl<A, IA: Default> From<ChangeSet<A>> for ChangeSet<A, IA>"],["impl<A, K> From<ChangeSet<K>> for ChangeSet<A, ChangeSet<K>>"],["impl From<Hash> for DescriptorId"],["impl From<DescriptorId> for Hash"]], "bdk_coin_select":[["impl From<usize> for BnbLimit"],["impl From<Duration> for BnbLimit"]], "bdk_file_store":[["impl From<Error> for IterError"],["impl From<Error> for FileError"]], "bdk_tmp_plan":[["impl From<Error> for SigningError"],["impl From<Error> for SigningError"]], +"bdk_wallet":[["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<HexToBytesError> for Error"],["impl From<PolicyError> for Error"],["impl From<bool> for Satisfaction"],["impl From<SatisfiableItem> for Policy"],["impl<Ctx: ScriptContext> From<Xpub> for ExtendedKey<Ctx>"],["impl<Ctx: ScriptContext> From<Xpriv> 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 CreateTxError"],["impl From<PolicyError> for CreateTxError"],["impl From<MiniscriptPsbtError> for CreateTxError"],["impl From<Error> for CreateTxError"],["impl From<Error> for CreateTxError"],["impl From<FullScanResult<KeychainKind, ConfirmationTimeHeightAnchor>> for Update"],["impl From<SyncResult<ConfirmationTimeHeightAnchor>> for Update"],["impl From<BTreeMap<u32, Option<BlockHash>, Global>> for ChangeSet"],["impl From<ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>> for ChangeSet"]], "example_bitcoind_rpc_polling":[["impl From<RpcArgs> for Auth"]] };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 5782ca4804..8890b7f31a 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,6 +1,6 @@ (function() {var implementors = { -"bdk":[["impl Default for Condition"],["impl Default for PrivateKeyGenerateOptions"],["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 Update"],["impl Default for ChangeSet"]], "bdk_chain":[["impl<I> Default for SpkTxOutIndex<I>"],["impl Default for BlockId"],["impl Default for ConfirmationHeightAnchor"],["impl Default for ConfirmationTimeHeightAnchor"],["impl<A, I: Default> Default for IndexedTxGraph<A, I>"],["impl<A, IA: Default> Default for ChangeSet<A, IA>"],["impl<K> Default for ChangeSet<K>"],["impl<K> Default for KeychainTxOutIndex<K>"],["impl Default for Balance"],["impl<A> Default for TxGraph<A>"],["impl<A> Default for ChangeSet<A>"]], "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>"]], +"bdk_wallet":[["impl Default for Condition"],["impl Default for PrivateKeyGenerateOptions"],["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 Update"],["impl Default for ChangeSet"]], "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 0076c5033e..731f5b687f 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,7 +1,7 @@ (function() {var implementors = { -"bdk":[["impl Error for Error"],["impl Error for PolicyError"],["impl Error for KeyError"],["impl Error for Error"],["impl Error for SignerError"],["impl Error for AddUtxoError"],["impl Error for AddForeignUtxoError"],["impl Error for AllowShrinkingError"],["impl Error for MiniscriptPsbtError"],["impl Error for CreateTxError"],["impl Error for BuildFeeBumpError"],["impl Error for NewError"],["impl Error for LoadError"],["impl Error for NewOrLoadError"],["impl Error for InsertTxError"],["impl Error for ApplyBlockError"]], "bdk_chain":[["impl Error for MissingGenesisError"],["impl Error for AlterCheckPointError"],["impl Error for CannotConnectError"],["impl Error for ApplyHeaderError"],["impl Error for CalculateFeeError"]], "bdk_coin_select":[["impl Error for SelectionError"]], "bdk_file_store":[["impl Error for IterError"],["impl<C: Debug> Error for AggregateChangesetsError<C>"],["impl Error for FileError"]], -"bdk_tmp_plan":[["impl Error for SigningError"]] +"bdk_tmp_plan":[["impl Error for SigningError"]], +"bdk_wallet":[["impl Error for Error"],["impl Error for PolicyError"],["impl Error for KeyError"],["impl Error for Error"],["impl Error for SignerError"],["impl Error for AddUtxoError"],["impl Error for AddForeignUtxoError"],["impl Error for AllowShrinkingError"],["impl Error for MiniscriptPsbtError"],["impl Error for CreateTxError"],["impl Error for BuildFeeBumpError"],["impl Error for NewError"],["impl Error for LoadError"],["impl Error for NewOrLoadError"],["impl Error for InsertTxError"],["impl Error for ApplyBlockError"]] };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 d2fab289c7..26dfb1436c 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,5 +1,4 @@ (function() {var implementors = { -"bdk":[["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 LocalOutput"],["impl Debug for WeightedUtxo"],["impl Debug for Utxo"],["impl Debug for Error"],["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, Cs: Debug, Ctx: Debug> Debug for TxBuilder<'a, Cs, Ctx>"],["impl Debug for AddUtxoError"],["impl Debug for AddForeignUtxoError"],["impl Debug for AllowShrinkingError"],["impl Debug for TxOrdering"],["impl Debug for ChangeSpendPolicy"],["impl Debug for MiniscriptPsbtError"],["impl Debug for CreateTxError"],["impl Debug for BuildFeeBumpError"],["impl Debug for Wallet"],["impl Debug for Update"],["impl Debug for ChangeSet"],["impl Debug for AddressInfo"],["impl Debug for NewError"],["impl Debug for LoadError"],["impl Debug for NewOrLoadError"],["impl Debug for InsertTxError"],["impl Debug for ApplyBlockError"]], "bdk_bitcoind_rpc":[["impl<B: Debug> Debug for BlockEvent<B>"]], "bdk_chain":[["impl<I: Debug> Debug for SpkTxOutIndex<I>"],["impl<A: Debug> Debug for ChainPosition<A>"],["impl Debug for ConfirmationTime"],["impl Debug for BlockId"],["impl Debug for ConfirmationHeightAnchor"],["impl Debug for ConfirmationTimeHeightAnchor"],["impl<A: Debug> Debug for FullTxOut<A>"],["impl<A: Debug, I: Debug> Debug for IndexedTxGraph<A, I>"],["impl<A: Debug, IA: Debug> Debug for ChangeSet<A, IA>"],["impl<K: Debug> Debug for ChangeSet<K>"],["impl<K: Debug> Debug for KeychainTxOutIndex<K>"],["impl Debug for Balance"],["impl Debug for CheckPoint"],["impl Debug for LocalChain"],["impl Debug for MissingGenesisError"],["impl Debug for AlterCheckPointError"],["impl Debug for CannotConnectError"],["impl Debug for ApplyHeaderError"],["impl<A: Debug> Debug for TxGraph<A>"],["impl<'a, T: Debug, A: Debug> Debug for TxNode<'a, T, A>"],["impl<'a, T: Debug, A: Debug> Debug for CanonicalTx<'a, T, A>"],["impl Debug for CalculateFeeError"],["impl<A: Debug> Debug for ChangeSet<A>"],["impl Debug for DescriptorId"]], "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"]], @@ -7,6 +6,7 @@ "bdk_hwi":[["impl Debug for HWISigner"]], "bdk_persist":[["impl<C: Debug> Debug for Persist<C>"]], "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>"]], +"bdk_wallet":[["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 LocalOutput"],["impl Debug for WeightedUtxo"],["impl Debug for Utxo"],["impl Debug for Error"],["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, Cs: Debug, Ctx: Debug> Debug for TxBuilder<'a, Cs, Ctx>"],["impl Debug for AddUtxoError"],["impl Debug for AddForeignUtxoError"],["impl Debug for AllowShrinkingError"],["impl Debug for TxOrdering"],["impl Debug for ChangeSpendPolicy"],["impl Debug for MiniscriptPsbtError"],["impl Debug for CreateTxError"],["impl Debug for BuildFeeBumpError"],["impl Debug for Wallet"],["impl Debug for Update"],["impl Debug for ChangeSet"],["impl Debug for AddressInfo"],["impl Debug for NewError"],["impl Debug for LoadError"],["impl Debug for NewOrLoadError"],["impl Debug for InsertTxError"],["impl Debug for ApplyBlockError"]], "example_bitcoind_rpc_polling":[["impl Debug for Emission"],["impl Debug for RpcArgs"],["impl Debug for RpcCommands"]], "example_cli":[["impl<CS: Debug + Subcommand, S: Debug + Args> Debug for Commands<CS, S>"],["impl Debug for CoinSelectionAlgo"],["impl Debug for AddressCmd"],["impl Debug for TxOutCmd"],["impl Debug for Keychain"]], "example_electrum":[["impl Debug for ElectrumCommands"],["impl Debug for ElectrumArgs"],["impl Debug for ScanOptions"]], 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 61a7d3464d..58d7c3c703 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,8 +1,8 @@ (function() {var implementors = { -"bdk":[["impl Display for Error"],["impl Display for PolicyError"],["impl Display for KeyError"],["impl Display for Error"],["impl Display for FullyNodedExport"],["impl Display for SignerError"],["impl Display for AddUtxoError"],["impl Display for AddForeignUtxoError"],["impl Display for AllowShrinkingError"],["impl Display for MiniscriptPsbtError"],["impl Display for CreateTxError"],["impl Display for BuildFeeBumpError"],["impl Display for AddressInfo"],["impl Display for NewError"],["impl Display for LoadError"],["impl Display for NewOrLoadError"],["impl Display for InsertTxError"],["impl Display for ApplyBlockError"]], "bdk_chain":[["impl Display for Balance"],["impl Display for MissingGenesisError"],["impl Display for AlterCheckPointError"],["impl Display for CannotConnectError"],["impl Display for ApplyHeaderError"],["impl Display for CalculateFeeError"],["impl Display for DescriptorId"]], "bdk_coin_select":[["impl Display for SelectionError"],["impl Display for SelectionConstraint"],["impl Display for ExcessStrategyKind"]], "bdk_file_store":[["impl Display for IterError"],["impl<C> Display for AggregateChangesetsError<C>"],["impl Display for FileError"]], "bdk_tmp_plan":[["impl Display for SigningError"]], +"bdk_wallet":[["impl Display for Error"],["impl Display for PolicyError"],["impl Display for KeyError"],["impl Display for Error"],["impl Display for FullyNodedExport"],["impl Display for SignerError"],["impl Display for AddUtxoError"],["impl Display for AddForeignUtxoError"],["impl Display for AllowShrinkingError"],["impl Display for MiniscriptPsbtError"],["impl Display for CreateTxError"],["impl Display for BuildFeeBumpError"],["impl Display for AddressInfo"],["impl Display for NewError"],["impl Display for LoadError"],["impl Display for NewOrLoadError"],["impl Display for InsertTxError"],["impl Display for ApplyBlockError"]], "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 5b6c109681..065747e4c9 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,5 +1,5 @@ (function() {var implementors = { -"bdk":[["impl Hash for PkOrF"],["impl Hash for Condition"],["impl Hash for KeychainKind"],["impl Hash for LocalOutput"],["impl Hash for SignerId"],["impl Hash for TxOrdering"],["impl Hash for ChangeSpendPolicy"]], "bdk_chain":[["impl<A: Hash> Hash for ChainPosition<A>"],["impl Hash for ConfirmationTime"],["impl Hash for BlockId"],["impl Hash for ConfirmationHeightAnchor"],["impl Hash for ConfirmationTimeHeightAnchor"],["impl Hash for DescriptorId"]], -"bdk_coin_select":[["impl Hash for ExcessStrategyKind"]] +"bdk_coin_select":[["impl Hash for ExcessStrategyKind"]], +"bdk_wallet":[["impl Hash for PkOrF"],["impl Hash for Condition"],["impl Hash for KeychainKind"],["impl Hash for LocalOutput"],["impl Hash for SignerId"],["impl Hash for TxOrdering"],["impl Hash for ChangeSpendPolicy"]] };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 704da2da20..a80e0f1201 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,6 +1,6 @@ (function() {var implementors = { -"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 LargestFirstCoinSelection"],["impl Copy for OldestFirstCoinSelection"],["impl Copy for SignerContext"],["impl Copy for TxOrdering"],["impl Copy for ChangeSpendPolicy"]], "bdk_chain":[["impl<A: Copy> Copy for ChainPosition<A>"],["impl Copy for ConfirmationTime"],["impl Copy for BlockId"],["impl Copy for ConfirmationHeightAnchor"],["impl Copy for ConfirmationTimeHeightAnchor"],["impl Copy for DescriptorId"]], "bdk_coin_select":[["impl Copy for WeightedValue"],["impl Copy for CoinSelectorOpt"],["impl Copy for SelectionConstraint"],["impl Copy for ExcessStrategyKind"],["impl Copy for ExcessStrategy"]], +"bdk_wallet":[["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 LargestFirstCoinSelection"],["impl Copy for OldestFirstCoinSelection"],["impl Copy for SignerContext"],["impl Copy for TxOrdering"],["impl Copy for ChangeSpendPolicy"]], "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 283e6d5caf..b976ded3d2 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,5 +1,4 @@ (function() {var implementors = { -"bdk":[["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 P2TR<K>where
    K: Freeze,
",1,["bdk::descriptor::template::P2TR"]],["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<K> Freeze for Bip86<K>where
    K: Freeze,
",1,["bdk::descriptor::template::Bip86"]],["impl<K> Freeze for Bip86Public<K>where
    K: Freeze,
",1,["bdk::descriptor::template::Bip86Public"]],["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 LocalOutput",1,["bdk::types::LocalOutput"]],["impl Freeze for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Freeze for Utxo",1,["bdk::types::Utxo"]],["impl Freeze for Error",1,["bdk::wallet::coin_selection::Error"]],["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, Cs, Ctx> Freeze for TxBuilder<'a, Cs, Ctx>where
    Cs: Freeze,
",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Freeze for AddUtxoError",1,["bdk::wallet::tx_builder::AddUtxoError"]],["impl Freeze for AddForeignUtxoError",1,["bdk::wallet::tx_builder::AddForeignUtxoError"]],["impl Freeze for AllowShrinkingError",1,["bdk::wallet::tx_builder::AllowShrinkingError"]],["impl Freeze for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Freeze for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl Freeze for MiniscriptPsbtError",1,["bdk::wallet::error::MiniscriptPsbtError"]],["impl Freeze for CreateTxError",1,["bdk::wallet::error::CreateTxError"]],["impl Freeze for BuildFeeBumpError",1,["bdk::wallet::error::BuildFeeBumpError"]],["impl Freeze for Wallet",1,["bdk::wallet::Wallet"]],["impl Freeze for Update",1,["bdk::wallet::Update"]],["impl Freeze for ChangeSet",1,["bdk::wallet::ChangeSet"]],["impl Freeze for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl Freeze for NewError",1,["bdk::wallet::NewError"]],["impl Freeze for LoadError",1,["bdk::wallet::LoadError"]],["impl !Freeze for NewOrLoadError",1,["bdk::wallet::NewOrLoadError"]],["impl Freeze for InsertTxError",1,["bdk::wallet::InsertTxError"]],["impl Freeze for ApplyBlockError",1,["bdk::wallet::ApplyBlockError"]]], "bdk_bitcoind_rpc":[["impl<'c, C> Freeze for Emitter<'c, C>",1,["bdk_bitcoind_rpc::Emitter"]],["impl<B> Freeze for BlockEvent<B>where
    B: Freeze,
",1,["bdk_bitcoind_rpc::BlockEvent"]]], "bdk_chain":[["impl<I> Freeze for SpkTxOutIndex<I>",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl<A> Freeze for ChainPosition<A>where
    A: Freeze,
",1,["bdk_chain::chain_data::ChainPosition"]],["impl Freeze for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl Freeze for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl Freeze for ConfirmationHeightAnchor",1,["bdk_chain::chain_data::ConfirmationHeightAnchor"]],["impl Freeze for ConfirmationTimeHeightAnchor",1,["bdk_chain::chain_data::ConfirmationTimeHeightAnchor"]],["impl<A> Freeze for FullTxOut<A>where
    A: Freeze,
",1,["bdk_chain::chain_data::FullTxOut"]],["impl<A, I> Freeze for IndexedTxGraph<A, I>where
    I: Freeze,
",1,["bdk_chain::indexed_tx_graph::IndexedTxGraph"]],["impl<A, IA> Freeze for ChangeSet<A, IA>where
    IA: Freeze,
",1,["bdk_chain::indexed_tx_graph::ChangeSet"]],["impl<K> Freeze for ChangeSet<K>",1,["bdk_chain::keychain::txout_index::ChangeSet"]],["impl<K> Freeze for KeychainTxOutIndex<K>",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl Freeze for Balance",1,["bdk_chain::keychain::Balance"]],["impl Freeze for CheckPoint",1,["bdk_chain::local_chain::CheckPoint"]],["impl Freeze for CheckPointIter",1,["bdk_chain::local_chain::CheckPointIter"]],["impl Freeze for LocalChain",1,["bdk_chain::local_chain::LocalChain"]],["impl Freeze for MissingGenesisError",1,["bdk_chain::local_chain::MissingGenesisError"]],["impl Freeze for AlterCheckPointError",1,["bdk_chain::local_chain::AlterCheckPointError"]],["impl Freeze for CannotConnectError",1,["bdk_chain::local_chain::CannotConnectError"]],["impl Freeze for ApplyHeaderError",1,["bdk_chain::local_chain::ApplyHeaderError"]],["impl<A> Freeze for TxGraph<A>",1,["bdk_chain::tx_graph::TxGraph"]],["impl<'a, T, A> Freeze for TxNode<'a, T, A>where
    T: Freeze,
",1,["bdk_chain::tx_graph::TxNode"]],["impl<'a, T, A> Freeze for CanonicalTx<'a, T, A>where
    T: Freeze,
",1,["bdk_chain::tx_graph::CanonicalTx"]],["impl Freeze for CalculateFeeError",1,["bdk_chain::tx_graph::CalculateFeeError"]],["impl<A> Freeze for ChangeSet<A>",1,["bdk_chain::tx_graph::ChangeSet"]],["impl<'g, A, F> Freeze for TxAncestors<'g, A, F>where
    F: Freeze,
",1,["bdk_chain::tx_graph::TxAncestors"]],["impl<'g, A, F> Freeze for TxDescendants<'g, A, F>where
    F: Freeze,
",1,["bdk_chain::tx_graph::TxDescendants"]],["impl Freeze for DescriptorId",1,["bdk_chain::descriptor_ext::DescriptorId"]],["impl<D> Freeze for SpkIterator<D>where
    D: Freeze,
",1,["bdk_chain::spk_iter::SpkIterator"]],["impl Freeze for SyncRequest",1,["bdk_chain::spk_client::SyncRequest"]],["impl<A> Freeze for SyncResult<A>",1,["bdk_chain::spk_client::SyncResult"]],["impl<K> Freeze for FullScanRequest<K>",1,["bdk_chain::spk_client::FullScanRequest"]],["impl<K, A> Freeze for FullScanResult<K, A>",1,["bdk_chain::spk_client::FullScanResult"]]], "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"]]], @@ -9,6 +8,7 @@ "bdk_persist":[["impl<C> Freeze for Persist<C>where
    C: Freeze,
",1,["bdk_persist::persist::Persist"]]], "bdk_testenv":[["impl !Freeze for TestEnv",1,["bdk_testenv::TestEnv"]]], "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"]]], +"bdk_wallet":[["impl Freeze for Error",1,["bdk_wallet::descriptor::error::Error"]],["impl Freeze for PkOrF",1,["bdk_wallet::descriptor::policy::PkOrF"]],["impl Freeze for SatisfiableItem",1,["bdk_wallet::descriptor::policy::SatisfiableItem"]],["impl Freeze for Satisfaction",1,["bdk_wallet::descriptor::policy::Satisfaction"]],["impl Freeze for Policy",1,["bdk_wallet::descriptor::policy::Policy"]],["impl Freeze for Condition",1,["bdk_wallet::descriptor::policy::Condition"]],["impl Freeze for PolicyError",1,["bdk_wallet::descriptor::policy::PolicyError"]],["impl<'a> Freeze for BuildSatisfaction<'a>",1,["bdk_wallet::descriptor::policy::BuildSatisfaction"]],["impl<K> Freeze for P2Pkh<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::P2Pkh"]],["impl<K> Freeze for P2Wpkh_P2Sh<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Freeze for P2Wpkh<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::P2Wpkh"]],["impl<K> Freeze for P2TR<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::P2TR"]],["impl<K> Freeze for Bip44<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::Bip44"]],["impl<K> Freeze for Bip44Public<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::Bip44Public"]],["impl<K> Freeze for Bip49<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::Bip49"]],["impl<K> Freeze for Bip49Public<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::Bip49Public"]],["impl<K> Freeze for Bip84<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::Bip84"]],["impl<K> Freeze for Bip84Public<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::Bip84Public"]],["impl<K> Freeze for Bip86<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::Bip86"]],["impl<K> Freeze for Bip86Public<K>where
    K: Freeze,
",1,["bdk_wallet::descriptor::template::Bip86Public"]],["impl<Ctx> Freeze for DescriptorKey<Ctx>",1,["bdk_wallet::keys::DescriptorKey"]],["impl Freeze for ScriptContextEnum",1,["bdk_wallet::keys::ScriptContextEnum"]],["impl<Ctx> Freeze for ExtendedKey<Ctx>",1,["bdk_wallet::keys::ExtendedKey"]],["impl<K, Ctx> Freeze for GeneratedKey<K, Ctx>where
    K: Freeze,
",1,["bdk_wallet::keys::GeneratedKey"]],["impl Freeze for PrivateKeyGenerateOptions",1,["bdk_wallet::keys::PrivateKeyGenerateOptions"]],["impl Freeze for KeyError",1,["bdk_wallet::keys::KeyError"]],["impl Freeze for KeychainKind",1,["bdk_wallet::types::KeychainKind"]],["impl Freeze for LocalOutput",1,["bdk_wallet::types::LocalOutput"]],["impl Freeze for WeightedUtxo",1,["bdk_wallet::types::WeightedUtxo"]],["impl Freeze for Utxo",1,["bdk_wallet::types::Utxo"]],["impl Freeze for Error",1,["bdk_wallet::wallet::coin_selection::Error"]],["impl Freeze for Excess",1,["bdk_wallet::wallet::coin_selection::Excess"]],["impl Freeze for CoinSelectionResult",1,["bdk_wallet::wallet::coin_selection::CoinSelectionResult"]],["impl Freeze for LargestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Freeze for OldestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Freeze for BranchAndBoundCoinSelection",1,["bdk_wallet::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Freeze for FullyNodedExport",1,["bdk_wallet::wallet::export::FullyNodedExport"]],["impl Freeze for SignerId",1,["bdk_wallet::wallet::signer::SignerId"]],["impl Freeze for SignerError",1,["bdk_wallet::wallet::signer::SignerError"]],["impl Freeze for SignerContext",1,["bdk_wallet::wallet::signer::SignerContext"]],["impl<S> Freeze for SignerWrapper<S>where
    S: Freeze,
",1,["bdk_wallet::wallet::signer::SignerWrapper"]],["impl Freeze for SignerOrdering",1,["bdk_wallet::wallet::signer::SignerOrdering"]],["impl Freeze for SignersContainer",1,["bdk_wallet::wallet::signer::SignersContainer"]],["impl Freeze for SignOptions",1,["bdk_wallet::wallet::signer::SignOptions"]],["impl Freeze for TapLeavesOptions",1,["bdk_wallet::wallet::signer::TapLeavesOptions"]],["impl Freeze for CreateTx",1,["bdk_wallet::wallet::tx_builder::CreateTx"]],["impl Freeze for BumpFee",1,["bdk_wallet::wallet::tx_builder::BumpFee"]],["impl<'a, Cs, Ctx> Freeze for TxBuilder<'a, Cs, Ctx>where
    Cs: Freeze,
",1,["bdk_wallet::wallet::tx_builder::TxBuilder"]],["impl Freeze for AddUtxoError",1,["bdk_wallet::wallet::tx_builder::AddUtxoError"]],["impl Freeze for AddForeignUtxoError",1,["bdk_wallet::wallet::tx_builder::AddForeignUtxoError"]],["impl Freeze for AllowShrinkingError",1,["bdk_wallet::wallet::tx_builder::AllowShrinkingError"]],["impl Freeze for TxOrdering",1,["bdk_wallet::wallet::tx_builder::TxOrdering"]],["impl Freeze for ChangeSpendPolicy",1,["bdk_wallet::wallet::tx_builder::ChangeSpendPolicy"]],["impl Freeze for MiniscriptPsbtError",1,["bdk_wallet::wallet::error::MiniscriptPsbtError"]],["impl Freeze for CreateTxError",1,["bdk_wallet::wallet::error::CreateTxError"]],["impl Freeze for BuildFeeBumpError",1,["bdk_wallet::wallet::error::BuildFeeBumpError"]],["impl Freeze for Wallet",1,["bdk_wallet::wallet::Wallet"]],["impl Freeze for Update",1,["bdk_wallet::wallet::Update"]],["impl Freeze for ChangeSet",1,["bdk_wallet::wallet::ChangeSet"]],["impl Freeze for AddressInfo",1,["bdk_wallet::wallet::AddressInfo"]],["impl Freeze for NewError",1,["bdk_wallet::wallet::NewError"]],["impl Freeze for LoadError",1,["bdk_wallet::wallet::LoadError"]],["impl !Freeze for NewOrLoadError",1,["bdk_wallet::wallet::NewOrLoadError"]],["impl Freeze for InsertTxError",1,["bdk_wallet::wallet::InsertTxError"]],["impl Freeze for ApplyBlockError",1,["bdk_wallet::wallet::ApplyBlockError"]]], "example_bitcoind_rpc_polling":[["impl Freeze for Emission",1,["example_bitcoind_rpc_polling::Emission"]],["impl Freeze for RpcArgs",1,["example_bitcoind_rpc_polling::RpcArgs"]],["impl Freeze for RpcCommands",1,["example_bitcoind_rpc_polling::RpcCommands"]]], "example_cli":[["impl<CS, S> Freeze for Args<CS, S>where
    CS: Freeze,
    S: Freeze,
",1,["example_cli::Args"]],["impl<CS, S> Freeze for Commands<CS, S>where
    CS: Freeze,
    S: Freeze,
",1,["example_cli::Commands"]],["impl Freeze for CoinSelectionAlgo",1,["example_cli::CoinSelectionAlgo"]],["impl Freeze for AddressCmd",1,["example_cli::AddressCmd"]],["impl Freeze for TxOutCmd",1,["example_cli::TxOutCmd"]],["impl Freeze for Keychain",1,["example_cli::Keychain"]],["impl Freeze for CreateTxChange",1,["example_cli::CreateTxChange"]],["impl<CS, S, C> !Freeze for Init<CS, S, C>",1,["example_cli::Init"]]], "example_electrum":[["impl Freeze for ElectrumCommands",1,["example_electrum::ElectrumCommands"]],["impl Freeze for ElectrumArgs",1,["example_electrum::ElectrumArgs"]],["impl Freeze for ScanOptions",1,["example_electrum::ScanOptions"]]], 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 96f072132e..fa5911c1fc 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,5 +1,4 @@ (function() {var implementors = { -"bdk":[["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 P2TR<K>where
    K: Send,
",1,["bdk::descriptor::template::P2TR"]],["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<K> Send for Bip86<K>where
    K: Send,
",1,["bdk::descriptor::template::Bip86"]],["impl<K> Send for Bip86Public<K>where
    K: Send,
",1,["bdk::descriptor::template::Bip86Public"]],["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 LocalOutput",1,["bdk::types::LocalOutput"]],["impl Send for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Send for Utxo",1,["bdk::types::Utxo"]],["impl Send for Error",1,["bdk::wallet::coin_selection::Error"]],["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, Cs, Ctx> !Send for TxBuilder<'a, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Send for AddUtxoError",1,["bdk::wallet::tx_builder::AddUtxoError"]],["impl Send for AddForeignUtxoError",1,["bdk::wallet::tx_builder::AddForeignUtxoError"]],["impl Send for AllowShrinkingError",1,["bdk::wallet::tx_builder::AllowShrinkingError"]],["impl Send for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Send for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl Send for MiniscriptPsbtError",1,["bdk::wallet::error::MiniscriptPsbtError"]],["impl Send for CreateTxError",1,["bdk::wallet::error::CreateTxError"]],["impl Send for BuildFeeBumpError",1,["bdk::wallet::error::BuildFeeBumpError"]],["impl Send for Wallet",1,["bdk::wallet::Wallet"]],["impl Send for Update",1,["bdk::wallet::Update"]],["impl Send for ChangeSet",1,["bdk::wallet::ChangeSet"]],["impl Send for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl Send for NewError",1,["bdk::wallet::NewError"]],["impl Send for LoadError",1,["bdk::wallet::LoadError"]],["impl Send for NewOrLoadError",1,["bdk::wallet::NewOrLoadError"]],["impl Send for InsertTxError",1,["bdk::wallet::InsertTxError"]],["impl Send for ApplyBlockError",1,["bdk::wallet::ApplyBlockError"]]], "bdk_bitcoind_rpc":[["impl<'c, C> Send for Emitter<'c, C>where
    C: Sync,
",1,["bdk_bitcoind_rpc::Emitter"]],["impl<B> Send for BlockEvent<B>where
    B: Send,
",1,["bdk_bitcoind_rpc::BlockEvent"]]], "bdk_chain":[["impl<I> Send for SpkTxOutIndex<I>where
    I: Send,
",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl<A> Send for ChainPosition<A>where
    A: Send,
",1,["bdk_chain::chain_data::ChainPosition"]],["impl Send for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl Send for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl Send for ConfirmationHeightAnchor",1,["bdk_chain::chain_data::ConfirmationHeightAnchor"]],["impl Send for ConfirmationTimeHeightAnchor",1,["bdk_chain::chain_data::ConfirmationTimeHeightAnchor"]],["impl<A> Send for FullTxOut<A>where
    A: Send,
",1,["bdk_chain::chain_data::FullTxOut"]],["impl<A, I> Send for IndexedTxGraph<A, I>where
    A: Send,
    I: Send,
",1,["bdk_chain::indexed_tx_graph::IndexedTxGraph"]],["impl<A, IA> Send for ChangeSet<A, IA>where
    A: Send,
    IA: Send,
",1,["bdk_chain::indexed_tx_graph::ChangeSet"]],["impl<K> Send for ChangeSet<K>where
    K: Send,
",1,["bdk_chain::keychain::txout_index::ChangeSet"]],["impl<K> Send for KeychainTxOutIndex<K>where
    K: Send,
",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl Send for Balance",1,["bdk_chain::keychain::Balance"]],["impl Send for CheckPoint",1,["bdk_chain::local_chain::CheckPoint"]],["impl Send for CheckPointIter",1,["bdk_chain::local_chain::CheckPointIter"]],["impl Send for LocalChain",1,["bdk_chain::local_chain::LocalChain"]],["impl Send for MissingGenesisError",1,["bdk_chain::local_chain::MissingGenesisError"]],["impl Send for AlterCheckPointError",1,["bdk_chain::local_chain::AlterCheckPointError"]],["impl Send for CannotConnectError",1,["bdk_chain::local_chain::CannotConnectError"]],["impl Send for ApplyHeaderError",1,["bdk_chain::local_chain::ApplyHeaderError"]],["impl<A> Send for TxGraph<A>where
    A: Send,
",1,["bdk_chain::tx_graph::TxGraph"]],["impl<'a, T, A> Send for TxNode<'a, T, A>where
    A: Sync,
    T: Send,
",1,["bdk_chain::tx_graph::TxNode"]],["impl<'a, T, A> Send for CanonicalTx<'a, T, A>where
    A: Sync,
    T: Send,
",1,["bdk_chain::tx_graph::CanonicalTx"]],["impl Send for CalculateFeeError",1,["bdk_chain::tx_graph::CalculateFeeError"]],["impl<A> Send for ChangeSet<A>where
    A: Send,
",1,["bdk_chain::tx_graph::ChangeSet"]],["impl<'g, A, F> Send for TxAncestors<'g, A, F>where
    A: Sync,
    F: Send,
",1,["bdk_chain::tx_graph::TxAncestors"]],["impl<'g, A, F> Send for TxDescendants<'g, A, F>where
    A: Sync,
    F: Send,
",1,["bdk_chain::tx_graph::TxDescendants"]],["impl Send for DescriptorId",1,["bdk_chain::descriptor_ext::DescriptorId"]],["impl<D> Send for SpkIterator<D>where
    D: Send,
",1,["bdk_chain::spk_iter::SpkIterator"]],["impl Send for SyncRequest",1,["bdk_chain::spk_client::SyncRequest"]],["impl<A> Send for SyncResult<A>where
    A: Send,
",1,["bdk_chain::spk_client::SyncResult"]],["impl<K> Send for FullScanRequest<K>where
    K: Send,
",1,["bdk_chain::spk_client::FullScanRequest"]],["impl<K, A> Send for FullScanResult<K, A>where
    A: Send,
    K: Send,
",1,["bdk_chain::spk_client::FullScanResult"]]], "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"]]], @@ -9,6 +8,7 @@ "bdk_persist":[["impl<C> Send for Persist<C>where
    C: Send,
",1,["bdk_persist::persist::Persist"]]], "bdk_testenv":[["impl Send for TestEnv",1,["bdk_testenv::TestEnv"]]], "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"]]], +"bdk_wallet":[["impl Send for Error",1,["bdk_wallet::descriptor::error::Error"]],["impl Send for PkOrF",1,["bdk_wallet::descriptor::policy::PkOrF"]],["impl Send for SatisfiableItem",1,["bdk_wallet::descriptor::policy::SatisfiableItem"]],["impl Send for Satisfaction",1,["bdk_wallet::descriptor::policy::Satisfaction"]],["impl Send for Policy",1,["bdk_wallet::descriptor::policy::Policy"]],["impl Send for Condition",1,["bdk_wallet::descriptor::policy::Condition"]],["impl Send for PolicyError",1,["bdk_wallet::descriptor::policy::PolicyError"]],["impl<'a> Send for BuildSatisfaction<'a>",1,["bdk_wallet::descriptor::policy::BuildSatisfaction"]],["impl<K> Send for P2Pkh<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::P2Pkh"]],["impl<K> Send for P2Wpkh_P2Sh<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Send for P2Wpkh<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::P2Wpkh"]],["impl<K> Send for P2TR<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::P2TR"]],["impl<K> Send for Bip44<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::Bip44"]],["impl<K> Send for Bip44Public<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::Bip44Public"]],["impl<K> Send for Bip49<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::Bip49"]],["impl<K> Send for Bip49Public<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::Bip49Public"]],["impl<K> Send for Bip84<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::Bip84"]],["impl<K> Send for Bip84Public<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::Bip84Public"]],["impl<K> Send for Bip86<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::Bip86"]],["impl<K> Send for Bip86Public<K>where
    K: Send,
",1,["bdk_wallet::descriptor::template::Bip86Public"]],["impl<Ctx> Send for DescriptorKey<Ctx>where
    Ctx: Send,
",1,["bdk_wallet::keys::DescriptorKey"]],["impl Send for ScriptContextEnum",1,["bdk_wallet::keys::ScriptContextEnum"]],["impl<Ctx> Send for ExtendedKey<Ctx>where
    Ctx: Send,
",1,["bdk_wallet::keys::ExtendedKey"]],["impl<K, Ctx> Send for GeneratedKey<K, Ctx>where
    Ctx: Send,
    K: Send,
",1,["bdk_wallet::keys::GeneratedKey"]],["impl Send for PrivateKeyGenerateOptions",1,["bdk_wallet::keys::PrivateKeyGenerateOptions"]],["impl Send for KeyError",1,["bdk_wallet::keys::KeyError"]],["impl Send for KeychainKind",1,["bdk_wallet::types::KeychainKind"]],["impl Send for LocalOutput",1,["bdk_wallet::types::LocalOutput"]],["impl Send for WeightedUtxo",1,["bdk_wallet::types::WeightedUtxo"]],["impl Send for Utxo",1,["bdk_wallet::types::Utxo"]],["impl Send for Error",1,["bdk_wallet::wallet::coin_selection::Error"]],["impl Send for Excess",1,["bdk_wallet::wallet::coin_selection::Excess"]],["impl Send for CoinSelectionResult",1,["bdk_wallet::wallet::coin_selection::CoinSelectionResult"]],["impl Send for LargestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Send for OldestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Send for BranchAndBoundCoinSelection",1,["bdk_wallet::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Send for FullyNodedExport",1,["bdk_wallet::wallet::export::FullyNodedExport"]],["impl Send for SignerId",1,["bdk_wallet::wallet::signer::SignerId"]],["impl Send for SignerError",1,["bdk_wallet::wallet::signer::SignerError"]],["impl Send for SignerContext",1,["bdk_wallet::wallet::signer::SignerContext"]],["impl<S> Send for SignerWrapper<S>where
    S: Send,
",1,["bdk_wallet::wallet::signer::SignerWrapper"]],["impl Send for SignerOrdering",1,["bdk_wallet::wallet::signer::SignerOrdering"]],["impl Send for SignersContainer",1,["bdk_wallet::wallet::signer::SignersContainer"]],["impl Send for SignOptions",1,["bdk_wallet::wallet::signer::SignOptions"]],["impl Send for TapLeavesOptions",1,["bdk_wallet::wallet::signer::TapLeavesOptions"]],["impl Send for CreateTx",1,["bdk_wallet::wallet::tx_builder::CreateTx"]],["impl Send for BumpFee",1,["bdk_wallet::wallet::tx_builder::BumpFee"]],["impl<'a, Cs, Ctx> !Send for TxBuilder<'a, Cs, Ctx>",1,["bdk_wallet::wallet::tx_builder::TxBuilder"]],["impl Send for AddUtxoError",1,["bdk_wallet::wallet::tx_builder::AddUtxoError"]],["impl Send for AddForeignUtxoError",1,["bdk_wallet::wallet::tx_builder::AddForeignUtxoError"]],["impl Send for AllowShrinkingError",1,["bdk_wallet::wallet::tx_builder::AllowShrinkingError"]],["impl Send for TxOrdering",1,["bdk_wallet::wallet::tx_builder::TxOrdering"]],["impl Send for ChangeSpendPolicy",1,["bdk_wallet::wallet::tx_builder::ChangeSpendPolicy"]],["impl Send for MiniscriptPsbtError",1,["bdk_wallet::wallet::error::MiniscriptPsbtError"]],["impl Send for CreateTxError",1,["bdk_wallet::wallet::error::CreateTxError"]],["impl Send for BuildFeeBumpError",1,["bdk_wallet::wallet::error::BuildFeeBumpError"]],["impl Send for Wallet",1,["bdk_wallet::wallet::Wallet"]],["impl Send for Update",1,["bdk_wallet::wallet::Update"]],["impl Send for ChangeSet",1,["bdk_wallet::wallet::ChangeSet"]],["impl Send for AddressInfo",1,["bdk_wallet::wallet::AddressInfo"]],["impl Send for NewError",1,["bdk_wallet::wallet::NewError"]],["impl Send for LoadError",1,["bdk_wallet::wallet::LoadError"]],["impl Send for NewOrLoadError",1,["bdk_wallet::wallet::NewOrLoadError"]],["impl Send for InsertTxError",1,["bdk_wallet::wallet::InsertTxError"]],["impl Send for ApplyBlockError",1,["bdk_wallet::wallet::ApplyBlockError"]]], "example_bitcoind_rpc_polling":[["impl Send for Emission",1,["example_bitcoind_rpc_polling::Emission"]],["impl Send for RpcArgs",1,["example_bitcoind_rpc_polling::RpcArgs"]],["impl Send for RpcCommands",1,["example_bitcoind_rpc_polling::RpcCommands"]]], "example_cli":[["impl<CS, S> Send for Args<CS, S>where
    CS: Send,
    S: Send,
",1,["example_cli::Args"]],["impl<CS, S> Send for Commands<CS, S>where
    CS: Send,
    S: Send,
",1,["example_cli::Commands"]],["impl Send for CoinSelectionAlgo",1,["example_cli::CoinSelectionAlgo"]],["impl Send for AddressCmd",1,["example_cli::AddressCmd"]],["impl Send for TxOutCmd",1,["example_cli::TxOutCmd"]],["impl Send for Keychain",1,["example_cli::Keychain"]],["impl Send for CreateTxChange",1,["example_cli::CreateTxChange"]],["impl<CS, S, C> Send for Init<CS, S, C>where
    C: Send,
    CS: Send,
    S: Send,
",1,["example_cli::Init"]]], "example_electrum":[["impl Send for ElectrumCommands",1,["example_electrum::ElectrumCommands"]],["impl Send for ElectrumArgs",1,["example_electrum::ElectrumArgs"]],["impl Send for ScanOptions",1,["example_electrum::ScanOptions"]]], 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 c13297aba7..defca81edd 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,6 +1,6 @@ (function() {var implementors = { -"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 LocalOutput"],["impl StructuralEq for WeightedUtxo"],["impl StructuralEq for Utxo"],["impl StructuralEq for SignerId"],["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<A> StructuralEq for ChainPosition<A>"],["impl StructuralEq for ConfirmationTime"],["impl StructuralEq for BlockId"],["impl StructuralEq for ConfirmationHeightAnchor"],["impl StructuralEq for ConfirmationTimeHeightAnchor"],["impl<A> StructuralEq for FullTxOut<A>"],["impl StructuralEq for Balance"],["impl<'a, T, A> StructuralEq for TxNode<'a, T, A>"],["impl<'a, T, A> StructuralEq for CanonicalTx<'a, T, A>"],["impl StructuralEq for CalculateFeeError"],["impl StructuralEq for DescriptorId"]], "bdk_coin_select":[["impl StructuralEq for SelectionConstraint"],["impl StructuralEq for ExcessStrategyKind"]], +"bdk_wallet":[["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 LocalOutput"],["impl StructuralEq for WeightedUtxo"],["impl StructuralEq for Utxo"],["impl StructuralEq for SignerId"],["impl StructuralEq for SignerContext"],["impl StructuralEq for SignerOrdering"],["impl StructuralEq for TapLeavesOptions"],["impl StructuralEq for TxOrdering"],["impl StructuralEq for ChangeSpendPolicy"],["impl StructuralEq for AddressInfo"]], "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 e6efc0ee0f..f8cee7410e 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,7 +1,7 @@ (function() {var implementors = { -"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 LocalOutput"],["impl StructuralPartialEq for WeightedUtxo"],["impl StructuralPartialEq for Utxo"],["impl StructuralPartialEq for SignerId"],["impl StructuralPartialEq for SignerContext"],["impl StructuralPartialEq for SignerOrdering"],["impl StructuralPartialEq for TapLeavesOptions"],["impl StructuralPartialEq for TxOrdering"],["impl StructuralPartialEq for ChangeSpendPolicy"],["impl StructuralPartialEq for ChangeSet"],["impl StructuralPartialEq for AddressInfo"]], "bdk_chain":[["impl<A> StructuralPartialEq for ChainPosition<A>"],["impl StructuralPartialEq for ConfirmationTime"],["impl StructuralPartialEq for BlockId"],["impl StructuralPartialEq for ConfirmationHeightAnchor"],["impl StructuralPartialEq for ConfirmationTimeHeightAnchor"],["impl<A> StructuralPartialEq for FullTxOut<A>"],["impl<A, IA> StructuralPartialEq for ChangeSet<A, IA>"],["impl<K> StructuralPartialEq for ChangeSet<K>"],["impl StructuralPartialEq for Balance"],["impl StructuralPartialEq for LocalChain"],["impl StructuralPartialEq for MissingGenesisError"],["impl StructuralPartialEq for AlterCheckPointError"],["impl StructuralPartialEq for CannotConnectError"],["impl StructuralPartialEq for ApplyHeaderError"],["impl<A> StructuralPartialEq for TxGraph<A>"],["impl<'a, T, A> StructuralPartialEq for TxNode<'a, T, A>"],["impl<'a, T, A> StructuralPartialEq for CanonicalTx<'a, T, A>"],["impl StructuralPartialEq for CalculateFeeError"],["impl<A> StructuralPartialEq for ChangeSet<A>"],["impl StructuralPartialEq for DescriptorId"]], "bdk_coin_select":[["impl StructuralPartialEq for SelectionConstraint"],["impl StructuralPartialEq for ExcessStrategyKind"]], +"bdk_wallet":[["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 LocalOutput"],["impl StructuralPartialEq for WeightedUtxo"],["impl StructuralPartialEq for Utxo"],["impl StructuralPartialEq for SignerId"],["impl StructuralPartialEq for SignerContext"],["impl StructuralPartialEq for SignerOrdering"],["impl StructuralPartialEq for TapLeavesOptions"],["impl StructuralPartialEq for TxOrdering"],["impl StructuralPartialEq for ChangeSpendPolicy"],["impl StructuralPartialEq for ChangeSet"],["impl StructuralPartialEq for AddressInfo"]], "example_cli":[["impl StructuralPartialEq for Keychain"]], "example_electrum":[["impl StructuralPartialEq for ScanOptions"]], "example_esplora":[["impl StructuralPartialEq for ScanOptions"]] 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 3154726de7..b119c3bf40 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,5 +1,4 @@ (function() {var implementors = { -"bdk":[["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 P2TR<K>where
    K: Sync,
",1,["bdk::descriptor::template::P2TR"]],["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<K> Sync for Bip86<K>where
    K: Sync,
",1,["bdk::descriptor::template::Bip86"]],["impl<K> Sync for Bip86Public<K>where
    K: Sync,
",1,["bdk::descriptor::template::Bip86Public"]],["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 LocalOutput",1,["bdk::types::LocalOutput"]],["impl Sync for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Sync for Utxo",1,["bdk::types::Utxo"]],["impl Sync for Error",1,["bdk::wallet::coin_selection::Error"]],["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, Cs, Ctx> !Sync for TxBuilder<'a, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Sync for AddUtxoError",1,["bdk::wallet::tx_builder::AddUtxoError"]],["impl Sync for AddForeignUtxoError",1,["bdk::wallet::tx_builder::AddForeignUtxoError"]],["impl Sync for AllowShrinkingError",1,["bdk::wallet::tx_builder::AllowShrinkingError"]],["impl Sync for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Sync for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl Sync for MiniscriptPsbtError",1,["bdk::wallet::error::MiniscriptPsbtError"]],["impl Sync for CreateTxError",1,["bdk::wallet::error::CreateTxError"]],["impl Sync for BuildFeeBumpError",1,["bdk::wallet::error::BuildFeeBumpError"]],["impl Sync for Wallet",1,["bdk::wallet::Wallet"]],["impl Sync for Update",1,["bdk::wallet::Update"]],["impl Sync for ChangeSet",1,["bdk::wallet::ChangeSet"]],["impl Sync for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl Sync for NewError",1,["bdk::wallet::NewError"]],["impl Sync for LoadError",1,["bdk::wallet::LoadError"]],["impl Sync for NewOrLoadError",1,["bdk::wallet::NewOrLoadError"]],["impl Sync for InsertTxError",1,["bdk::wallet::InsertTxError"]],["impl Sync for ApplyBlockError",1,["bdk::wallet::ApplyBlockError"]]], "bdk_bitcoind_rpc":[["impl<'c, C> Sync for Emitter<'c, C>where
    C: Sync,
",1,["bdk_bitcoind_rpc::Emitter"]],["impl<B> Sync for BlockEvent<B>where
    B: Sync,
",1,["bdk_bitcoind_rpc::BlockEvent"]]], "bdk_chain":[["impl<I> Sync for SpkTxOutIndex<I>where
    I: Sync,
",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl<A> Sync for ChainPosition<A>where
    A: Sync,
",1,["bdk_chain::chain_data::ChainPosition"]],["impl Sync for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl Sync for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl Sync for ConfirmationHeightAnchor",1,["bdk_chain::chain_data::ConfirmationHeightAnchor"]],["impl Sync for ConfirmationTimeHeightAnchor",1,["bdk_chain::chain_data::ConfirmationTimeHeightAnchor"]],["impl<A> Sync for FullTxOut<A>where
    A: Sync,
",1,["bdk_chain::chain_data::FullTxOut"]],["impl<A, I> Sync for IndexedTxGraph<A, I>where
    A: Sync,
    I: Sync,
",1,["bdk_chain::indexed_tx_graph::IndexedTxGraph"]],["impl<A, IA> Sync for ChangeSet<A, IA>where
    A: Sync,
    IA: Sync,
",1,["bdk_chain::indexed_tx_graph::ChangeSet"]],["impl<K> Sync for ChangeSet<K>where
    K: Sync,
",1,["bdk_chain::keychain::txout_index::ChangeSet"]],["impl<K> Sync for KeychainTxOutIndex<K>where
    K: Sync,
",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl Sync for Balance",1,["bdk_chain::keychain::Balance"]],["impl Sync for CheckPoint",1,["bdk_chain::local_chain::CheckPoint"]],["impl Sync for CheckPointIter",1,["bdk_chain::local_chain::CheckPointIter"]],["impl Sync for LocalChain",1,["bdk_chain::local_chain::LocalChain"]],["impl Sync for MissingGenesisError",1,["bdk_chain::local_chain::MissingGenesisError"]],["impl Sync for AlterCheckPointError",1,["bdk_chain::local_chain::AlterCheckPointError"]],["impl Sync for CannotConnectError",1,["bdk_chain::local_chain::CannotConnectError"]],["impl Sync for ApplyHeaderError",1,["bdk_chain::local_chain::ApplyHeaderError"]],["impl<A> Sync for TxGraph<A>where
    A: Sync,
",1,["bdk_chain::tx_graph::TxGraph"]],["impl<'a, T, A> Sync for TxNode<'a, T, A>where
    A: Sync,
    T: Sync,
",1,["bdk_chain::tx_graph::TxNode"]],["impl<'a, T, A> Sync for CanonicalTx<'a, T, A>where
    A: Sync,
    T: Sync,
",1,["bdk_chain::tx_graph::CanonicalTx"]],["impl Sync for CalculateFeeError",1,["bdk_chain::tx_graph::CalculateFeeError"]],["impl<A> Sync for ChangeSet<A>where
    A: Sync,
",1,["bdk_chain::tx_graph::ChangeSet"]],["impl<'g, A, F> Sync for TxAncestors<'g, A, F>where
    A: Sync,
    F: Sync,
",1,["bdk_chain::tx_graph::TxAncestors"]],["impl<'g, A, F> Sync for TxDescendants<'g, A, F>where
    A: Sync,
    F: Sync,
",1,["bdk_chain::tx_graph::TxDescendants"]],["impl Sync for DescriptorId",1,["bdk_chain::descriptor_ext::DescriptorId"]],["impl<D> Sync for SpkIterator<D>where
    D: Sync,
",1,["bdk_chain::spk_iter::SpkIterator"]],["impl !Sync for SyncRequest",1,["bdk_chain::spk_client::SyncRequest"]],["impl<A> Sync for SyncResult<A>where
    A: Sync,
",1,["bdk_chain::spk_client::SyncResult"]],["impl<K> !Sync for FullScanRequest<K>",1,["bdk_chain::spk_client::FullScanRequest"]],["impl<K, A> Sync for FullScanResult<K, A>where
    A: Sync,
    K: Sync,
",1,["bdk_chain::spk_client::FullScanResult"]]], "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"]]], @@ -9,6 +8,7 @@ "bdk_persist":[["impl<C> Sync for Persist<C>where
    C: Sync,
",1,["bdk_persist::persist::Persist"]]], "bdk_testenv":[["impl Sync for TestEnv",1,["bdk_testenv::TestEnv"]]], "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"]]], +"bdk_wallet":[["impl Sync for Error",1,["bdk_wallet::descriptor::error::Error"]],["impl Sync for PkOrF",1,["bdk_wallet::descriptor::policy::PkOrF"]],["impl Sync for SatisfiableItem",1,["bdk_wallet::descriptor::policy::SatisfiableItem"]],["impl Sync for Satisfaction",1,["bdk_wallet::descriptor::policy::Satisfaction"]],["impl Sync for Policy",1,["bdk_wallet::descriptor::policy::Policy"]],["impl Sync for Condition",1,["bdk_wallet::descriptor::policy::Condition"]],["impl Sync for PolicyError",1,["bdk_wallet::descriptor::policy::PolicyError"]],["impl<'a> Sync for BuildSatisfaction<'a>",1,["bdk_wallet::descriptor::policy::BuildSatisfaction"]],["impl<K> Sync for P2Pkh<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::P2Pkh"]],["impl<K> Sync for P2Wpkh_P2Sh<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Sync for P2Wpkh<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::P2Wpkh"]],["impl<K> Sync for P2TR<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::P2TR"]],["impl<K> Sync for Bip44<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::Bip44"]],["impl<K> Sync for Bip44Public<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::Bip44Public"]],["impl<K> Sync for Bip49<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::Bip49"]],["impl<K> Sync for Bip49Public<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::Bip49Public"]],["impl<K> Sync for Bip84<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::Bip84"]],["impl<K> Sync for Bip84Public<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::Bip84Public"]],["impl<K> Sync for Bip86<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::Bip86"]],["impl<K> Sync for Bip86Public<K>where
    K: Sync,
",1,["bdk_wallet::descriptor::template::Bip86Public"]],["impl<Ctx> Sync for DescriptorKey<Ctx>where
    Ctx: Sync,
",1,["bdk_wallet::keys::DescriptorKey"]],["impl Sync for ScriptContextEnum",1,["bdk_wallet::keys::ScriptContextEnum"]],["impl<Ctx> Sync for ExtendedKey<Ctx>where
    Ctx: Sync,
",1,["bdk_wallet::keys::ExtendedKey"]],["impl<K, Ctx> Sync for GeneratedKey<K, Ctx>where
    Ctx: Sync,
    K: Sync,
",1,["bdk_wallet::keys::GeneratedKey"]],["impl Sync for PrivateKeyGenerateOptions",1,["bdk_wallet::keys::PrivateKeyGenerateOptions"]],["impl Sync for KeyError",1,["bdk_wallet::keys::KeyError"]],["impl Sync for KeychainKind",1,["bdk_wallet::types::KeychainKind"]],["impl Sync for LocalOutput",1,["bdk_wallet::types::LocalOutput"]],["impl Sync for WeightedUtxo",1,["bdk_wallet::types::WeightedUtxo"]],["impl Sync for Utxo",1,["bdk_wallet::types::Utxo"]],["impl Sync for Error",1,["bdk_wallet::wallet::coin_selection::Error"]],["impl Sync for Excess",1,["bdk_wallet::wallet::coin_selection::Excess"]],["impl Sync for CoinSelectionResult",1,["bdk_wallet::wallet::coin_selection::CoinSelectionResult"]],["impl Sync for LargestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Sync for OldestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Sync for BranchAndBoundCoinSelection",1,["bdk_wallet::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Sync for FullyNodedExport",1,["bdk_wallet::wallet::export::FullyNodedExport"]],["impl Sync for SignerId",1,["bdk_wallet::wallet::signer::SignerId"]],["impl Sync for SignerError",1,["bdk_wallet::wallet::signer::SignerError"]],["impl Sync for SignerContext",1,["bdk_wallet::wallet::signer::SignerContext"]],["impl<S> Sync for SignerWrapper<S>where
    S: Sync,
",1,["bdk_wallet::wallet::signer::SignerWrapper"]],["impl Sync for SignerOrdering",1,["bdk_wallet::wallet::signer::SignerOrdering"]],["impl Sync for SignersContainer",1,["bdk_wallet::wallet::signer::SignersContainer"]],["impl Sync for SignOptions",1,["bdk_wallet::wallet::signer::SignOptions"]],["impl Sync for TapLeavesOptions",1,["bdk_wallet::wallet::signer::TapLeavesOptions"]],["impl Sync for CreateTx",1,["bdk_wallet::wallet::tx_builder::CreateTx"]],["impl Sync for BumpFee",1,["bdk_wallet::wallet::tx_builder::BumpFee"]],["impl<'a, Cs, Ctx> !Sync for TxBuilder<'a, Cs, Ctx>",1,["bdk_wallet::wallet::tx_builder::TxBuilder"]],["impl Sync for AddUtxoError",1,["bdk_wallet::wallet::tx_builder::AddUtxoError"]],["impl Sync for AddForeignUtxoError",1,["bdk_wallet::wallet::tx_builder::AddForeignUtxoError"]],["impl Sync for AllowShrinkingError",1,["bdk_wallet::wallet::tx_builder::AllowShrinkingError"]],["impl Sync for TxOrdering",1,["bdk_wallet::wallet::tx_builder::TxOrdering"]],["impl Sync for ChangeSpendPolicy",1,["bdk_wallet::wallet::tx_builder::ChangeSpendPolicy"]],["impl Sync for MiniscriptPsbtError",1,["bdk_wallet::wallet::error::MiniscriptPsbtError"]],["impl Sync for CreateTxError",1,["bdk_wallet::wallet::error::CreateTxError"]],["impl Sync for BuildFeeBumpError",1,["bdk_wallet::wallet::error::BuildFeeBumpError"]],["impl Sync for Wallet",1,["bdk_wallet::wallet::Wallet"]],["impl Sync for Update",1,["bdk_wallet::wallet::Update"]],["impl Sync for ChangeSet",1,["bdk_wallet::wallet::ChangeSet"]],["impl Sync for AddressInfo",1,["bdk_wallet::wallet::AddressInfo"]],["impl Sync for NewError",1,["bdk_wallet::wallet::NewError"]],["impl Sync for LoadError",1,["bdk_wallet::wallet::LoadError"]],["impl Sync for NewOrLoadError",1,["bdk_wallet::wallet::NewOrLoadError"]],["impl Sync for InsertTxError",1,["bdk_wallet::wallet::InsertTxError"]],["impl Sync for ApplyBlockError",1,["bdk_wallet::wallet::ApplyBlockError"]]], "example_bitcoind_rpc_polling":[["impl Sync for Emission",1,["example_bitcoind_rpc_polling::Emission"]],["impl Sync for RpcArgs",1,["example_bitcoind_rpc_polling::RpcArgs"]],["impl Sync for RpcCommands",1,["example_bitcoind_rpc_polling::RpcCommands"]]], "example_cli":[["impl<CS, S> Sync for Args<CS, S>where
    CS: Sync,
    S: Sync,
",1,["example_cli::Args"]],["impl<CS, S> Sync for Commands<CS, S>where
    CS: Sync,
    S: Sync,
",1,["example_cli::Commands"]],["impl Sync for CoinSelectionAlgo",1,["example_cli::CoinSelectionAlgo"]],["impl Sync for AddressCmd",1,["example_cli::AddressCmd"]],["impl Sync for TxOutCmd",1,["example_cli::TxOutCmd"]],["impl Sync for Keychain",1,["example_cli::Keychain"]],["impl Sync for CreateTxChange",1,["example_cli::CreateTxChange"]],["impl<CS, S, C> Sync for Init<CS, S, C>where
    C: Send + Sync,
    CS: Sync,
    S: Sync,
",1,["example_cli::Init"]]], "example_electrum":[["impl Sync for ElectrumCommands",1,["example_electrum::ElectrumCommands"]],["impl Sync for ElectrumArgs",1,["example_electrum::ElectrumArgs"]],["impl Sync for ScanOptions",1,["example_electrum::ScanOptions"]]], 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 0d6afdf107..437679cda3 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,5 +1,4 @@ (function() {var implementors = { -"bdk":[["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 P2TR<K>where
    K: Unpin,
",1,["bdk::descriptor::template::P2TR"]],["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<K> Unpin for Bip86<K>where
    K: Unpin,
",1,["bdk::descriptor::template::Bip86"]],["impl<K> Unpin for Bip86Public<K>where
    K: Unpin,
",1,["bdk::descriptor::template::Bip86Public"]],["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 LocalOutput",1,["bdk::types::LocalOutput"]],["impl Unpin for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl Unpin for Utxo",1,["bdk::types::Utxo"]],["impl Unpin for Error",1,["bdk::wallet::coin_selection::Error"]],["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, Cs, Ctx> Unpin for TxBuilder<'a, Cs, Ctx>where
    Cs: Unpin,
    Ctx: Unpin,
",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl Unpin for AddUtxoError",1,["bdk::wallet::tx_builder::AddUtxoError"]],["impl Unpin for AddForeignUtxoError",1,["bdk::wallet::tx_builder::AddForeignUtxoError"]],["impl Unpin for AllowShrinkingError",1,["bdk::wallet::tx_builder::AllowShrinkingError"]],["impl Unpin for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl Unpin for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl Unpin for MiniscriptPsbtError",1,["bdk::wallet::error::MiniscriptPsbtError"]],["impl Unpin for CreateTxError",1,["bdk::wallet::error::CreateTxError"]],["impl Unpin for BuildFeeBumpError",1,["bdk::wallet::error::BuildFeeBumpError"]],["impl Unpin for Wallet",1,["bdk::wallet::Wallet"]],["impl Unpin for Update",1,["bdk::wallet::Update"]],["impl Unpin for ChangeSet",1,["bdk::wallet::ChangeSet"]],["impl Unpin for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl Unpin for NewError",1,["bdk::wallet::NewError"]],["impl Unpin for LoadError",1,["bdk::wallet::LoadError"]],["impl Unpin for NewOrLoadError",1,["bdk::wallet::NewOrLoadError"]],["impl Unpin for InsertTxError",1,["bdk::wallet::InsertTxError"]],["impl Unpin for ApplyBlockError",1,["bdk::wallet::ApplyBlockError"]]], "bdk_bitcoind_rpc":[["impl<'c, C> Unpin for Emitter<'c, C>",1,["bdk_bitcoind_rpc::Emitter"]],["impl<B> Unpin for BlockEvent<B>where
    B: Unpin,
",1,["bdk_bitcoind_rpc::BlockEvent"]]], "bdk_chain":[["impl<I> Unpin for SpkTxOutIndex<I>where
    I: Unpin,
",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl<A> Unpin for ChainPosition<A>where
    A: Unpin,
",1,["bdk_chain::chain_data::ChainPosition"]],["impl Unpin for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl Unpin for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl Unpin for ConfirmationHeightAnchor",1,["bdk_chain::chain_data::ConfirmationHeightAnchor"]],["impl Unpin for ConfirmationTimeHeightAnchor",1,["bdk_chain::chain_data::ConfirmationTimeHeightAnchor"]],["impl<A> Unpin for FullTxOut<A>where
    A: Unpin,
",1,["bdk_chain::chain_data::FullTxOut"]],["impl<A, I> Unpin for IndexedTxGraph<A, I>where
    I: Unpin,
",1,["bdk_chain::indexed_tx_graph::IndexedTxGraph"]],["impl<A, IA> Unpin for ChangeSet<A, IA>where
    IA: Unpin,
",1,["bdk_chain::indexed_tx_graph::ChangeSet"]],["impl<K> Unpin for ChangeSet<K>",1,["bdk_chain::keychain::txout_index::ChangeSet"]],["impl<K> Unpin for KeychainTxOutIndex<K>",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl Unpin for Balance",1,["bdk_chain::keychain::Balance"]],["impl Unpin for CheckPoint",1,["bdk_chain::local_chain::CheckPoint"]],["impl Unpin for CheckPointIter",1,["bdk_chain::local_chain::CheckPointIter"]],["impl Unpin for LocalChain",1,["bdk_chain::local_chain::LocalChain"]],["impl Unpin for MissingGenesisError",1,["bdk_chain::local_chain::MissingGenesisError"]],["impl Unpin for AlterCheckPointError",1,["bdk_chain::local_chain::AlterCheckPointError"]],["impl Unpin for CannotConnectError",1,["bdk_chain::local_chain::CannotConnectError"]],["impl Unpin for ApplyHeaderError",1,["bdk_chain::local_chain::ApplyHeaderError"]],["impl<A> Unpin for TxGraph<A>",1,["bdk_chain::tx_graph::TxGraph"]],["impl<'a, T, A> Unpin for TxNode<'a, T, A>where
    T: Unpin,
",1,["bdk_chain::tx_graph::TxNode"]],["impl<'a, T, A> Unpin for CanonicalTx<'a, T, A>where
    T: Unpin,
",1,["bdk_chain::tx_graph::CanonicalTx"]],["impl Unpin for CalculateFeeError",1,["bdk_chain::tx_graph::CalculateFeeError"]],["impl<A> Unpin for ChangeSet<A>",1,["bdk_chain::tx_graph::ChangeSet"]],["impl<'g, A, F> Unpin for TxAncestors<'g, A, F>where
    F: Unpin,
",1,["bdk_chain::tx_graph::TxAncestors"]],["impl<'g, A, F> Unpin for TxDescendants<'g, A, F>where
    F: Unpin,
",1,["bdk_chain::tx_graph::TxDescendants"]],["impl Unpin for DescriptorId",1,["bdk_chain::descriptor_ext::DescriptorId"]],["impl<D> Unpin for SpkIterator<D>where
    D: Unpin,
",1,["bdk_chain::spk_iter::SpkIterator"]],["impl Unpin for SyncRequest",1,["bdk_chain::spk_client::SyncRequest"]],["impl<A> Unpin for SyncResult<A>",1,["bdk_chain::spk_client::SyncResult"]],["impl<K> Unpin for FullScanRequest<K>",1,["bdk_chain::spk_client::FullScanRequest"]],["impl<K, A> Unpin for FullScanResult<K, A>",1,["bdk_chain::spk_client::FullScanResult"]]], "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"]]], @@ -9,6 +8,7 @@ "bdk_persist":[["impl<C> Unpin for Persist<C>where
    C: Unpin,
",1,["bdk_persist::persist::Persist"]]], "bdk_testenv":[["impl Unpin for TestEnv",1,["bdk_testenv::TestEnv"]]], "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"]]], +"bdk_wallet":[["impl Unpin for Error",1,["bdk_wallet::descriptor::error::Error"]],["impl Unpin for PkOrF",1,["bdk_wallet::descriptor::policy::PkOrF"]],["impl Unpin for SatisfiableItem",1,["bdk_wallet::descriptor::policy::SatisfiableItem"]],["impl Unpin for Satisfaction",1,["bdk_wallet::descriptor::policy::Satisfaction"]],["impl Unpin for Policy",1,["bdk_wallet::descriptor::policy::Policy"]],["impl Unpin for Condition",1,["bdk_wallet::descriptor::policy::Condition"]],["impl Unpin for PolicyError",1,["bdk_wallet::descriptor::policy::PolicyError"]],["impl<'a> Unpin for BuildSatisfaction<'a>",1,["bdk_wallet::descriptor::policy::BuildSatisfaction"]],["impl<K> Unpin for P2Pkh<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::P2Pkh"]],["impl<K> Unpin for P2Wpkh_P2Sh<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> Unpin for P2Wpkh<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::P2Wpkh"]],["impl<K> Unpin for P2TR<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::P2TR"]],["impl<K> Unpin for Bip44<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::Bip44"]],["impl<K> Unpin for Bip44Public<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::Bip44Public"]],["impl<K> Unpin for Bip49<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::Bip49"]],["impl<K> Unpin for Bip49Public<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::Bip49Public"]],["impl<K> Unpin for Bip84<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::Bip84"]],["impl<K> Unpin for Bip84Public<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::Bip84Public"]],["impl<K> Unpin for Bip86<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::Bip86"]],["impl<K> Unpin for Bip86Public<K>where
    K: Unpin,
",1,["bdk_wallet::descriptor::template::Bip86Public"]],["impl<Ctx> Unpin for DescriptorKey<Ctx>where
    Ctx: Unpin,
",1,["bdk_wallet::keys::DescriptorKey"]],["impl Unpin for ScriptContextEnum",1,["bdk_wallet::keys::ScriptContextEnum"]],["impl<Ctx> Unpin for ExtendedKey<Ctx>where
    Ctx: Unpin,
",1,["bdk_wallet::keys::ExtendedKey"]],["impl<K, Ctx> Unpin for GeneratedKey<K, Ctx>where
    Ctx: Unpin,
    K: Unpin,
",1,["bdk_wallet::keys::GeneratedKey"]],["impl Unpin for PrivateKeyGenerateOptions",1,["bdk_wallet::keys::PrivateKeyGenerateOptions"]],["impl Unpin for KeyError",1,["bdk_wallet::keys::KeyError"]],["impl Unpin for KeychainKind",1,["bdk_wallet::types::KeychainKind"]],["impl Unpin for LocalOutput",1,["bdk_wallet::types::LocalOutput"]],["impl Unpin for WeightedUtxo",1,["bdk_wallet::types::WeightedUtxo"]],["impl Unpin for Utxo",1,["bdk_wallet::types::Utxo"]],["impl Unpin for Error",1,["bdk_wallet::wallet::coin_selection::Error"]],["impl Unpin for Excess",1,["bdk_wallet::wallet::coin_selection::Excess"]],["impl Unpin for CoinSelectionResult",1,["bdk_wallet::wallet::coin_selection::CoinSelectionResult"]],["impl Unpin for LargestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::LargestFirstCoinSelection"]],["impl Unpin for OldestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::OldestFirstCoinSelection"]],["impl Unpin for BranchAndBoundCoinSelection",1,["bdk_wallet::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl Unpin for FullyNodedExport",1,["bdk_wallet::wallet::export::FullyNodedExport"]],["impl Unpin for SignerId",1,["bdk_wallet::wallet::signer::SignerId"]],["impl Unpin for SignerError",1,["bdk_wallet::wallet::signer::SignerError"]],["impl Unpin for SignerContext",1,["bdk_wallet::wallet::signer::SignerContext"]],["impl<S> Unpin for SignerWrapper<S>where
    S: Unpin,
",1,["bdk_wallet::wallet::signer::SignerWrapper"]],["impl Unpin for SignerOrdering",1,["bdk_wallet::wallet::signer::SignerOrdering"]],["impl Unpin for SignersContainer",1,["bdk_wallet::wallet::signer::SignersContainer"]],["impl Unpin for SignOptions",1,["bdk_wallet::wallet::signer::SignOptions"]],["impl Unpin for TapLeavesOptions",1,["bdk_wallet::wallet::signer::TapLeavesOptions"]],["impl Unpin for CreateTx",1,["bdk_wallet::wallet::tx_builder::CreateTx"]],["impl Unpin for BumpFee",1,["bdk_wallet::wallet::tx_builder::BumpFee"]],["impl<'a, Cs, Ctx> Unpin for TxBuilder<'a, Cs, Ctx>where
    Cs: Unpin,
    Ctx: Unpin,
",1,["bdk_wallet::wallet::tx_builder::TxBuilder"]],["impl Unpin for AddUtxoError",1,["bdk_wallet::wallet::tx_builder::AddUtxoError"]],["impl Unpin for AddForeignUtxoError",1,["bdk_wallet::wallet::tx_builder::AddForeignUtxoError"]],["impl Unpin for AllowShrinkingError",1,["bdk_wallet::wallet::tx_builder::AllowShrinkingError"]],["impl Unpin for TxOrdering",1,["bdk_wallet::wallet::tx_builder::TxOrdering"]],["impl Unpin for ChangeSpendPolicy",1,["bdk_wallet::wallet::tx_builder::ChangeSpendPolicy"]],["impl Unpin for MiniscriptPsbtError",1,["bdk_wallet::wallet::error::MiniscriptPsbtError"]],["impl Unpin for CreateTxError",1,["bdk_wallet::wallet::error::CreateTxError"]],["impl Unpin for BuildFeeBumpError",1,["bdk_wallet::wallet::error::BuildFeeBumpError"]],["impl Unpin for Wallet",1,["bdk_wallet::wallet::Wallet"]],["impl Unpin for Update",1,["bdk_wallet::wallet::Update"]],["impl Unpin for ChangeSet",1,["bdk_wallet::wallet::ChangeSet"]],["impl Unpin for AddressInfo",1,["bdk_wallet::wallet::AddressInfo"]],["impl Unpin for NewError",1,["bdk_wallet::wallet::NewError"]],["impl Unpin for LoadError",1,["bdk_wallet::wallet::LoadError"]],["impl Unpin for NewOrLoadError",1,["bdk_wallet::wallet::NewOrLoadError"]],["impl Unpin for InsertTxError",1,["bdk_wallet::wallet::InsertTxError"]],["impl Unpin for ApplyBlockError",1,["bdk_wallet::wallet::ApplyBlockError"]]], "example_bitcoind_rpc_polling":[["impl Unpin for Emission",1,["example_bitcoind_rpc_polling::Emission"]],["impl Unpin for RpcArgs",1,["example_bitcoind_rpc_polling::RpcArgs"]],["impl Unpin for RpcCommands",1,["example_bitcoind_rpc_polling::RpcCommands"]]], "example_cli":[["impl<CS, S> Unpin for Args<CS, S>where
    CS: Unpin,
    S: Unpin,
",1,["example_cli::Args"]],["impl<CS, S> Unpin for Commands<CS, S>where
    CS: Unpin,
    S: Unpin,
",1,["example_cli::Commands"]],["impl Unpin for CoinSelectionAlgo",1,["example_cli::CoinSelectionAlgo"]],["impl Unpin for AddressCmd",1,["example_cli::AddressCmd"]],["impl Unpin for TxOutCmd",1,["example_cli::TxOutCmd"]],["impl Unpin for Keychain",1,["example_cli::Keychain"]],["impl Unpin for CreateTxChange",1,["example_cli::CreateTxChange"]],["impl<CS, S, C> Unpin for Init<CS, S, C>where
    C: Unpin,
    CS: Unpin,
    S: Unpin,
",1,["example_cli::Init"]]], "example_electrum":[["impl Unpin for ElectrumCommands",1,["example_electrum::ElectrumCommands"]],["impl Unpin for ElectrumArgs",1,["example_electrum::ElectrumArgs"]],["impl Unpin for ScanOptions",1,["example_electrum::ScanOptions"]]], 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 c0b3c9812d..ee08477745 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,4 +1,4 @@ (function() {var implementors = { -"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<'a, T, A> Deref for TxNode<'a, T, A>"]] +"bdk_chain":[["impl<'a, T, A> Deref for TxNode<'a, T, A>"]], +"bdk_wallet":[["impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx>"],["impl<S: Sized + Debug + Clone> Deref for SignerWrapper<S>"],["impl Deref for AddressInfo"]] };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 7256f76384..7df4e40b20 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,5 +1,4 @@ (function() {var implementors = { -"bdk":[["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 P2TR<K>where
    K: RefUnwindSafe,
",1,["bdk::descriptor::template::P2TR"]],["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<K> RefUnwindSafe for Bip86<K>where
    K: RefUnwindSafe,
",1,["bdk::descriptor::template::Bip86"]],["impl<K> RefUnwindSafe for Bip86Public<K>where
    K: RefUnwindSafe,
",1,["bdk::descriptor::template::Bip86Public"]],["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 LocalOutput",1,["bdk::types::LocalOutput"]],["impl RefUnwindSafe for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl RefUnwindSafe for Utxo",1,["bdk::types::Utxo"]],["impl RefUnwindSafe for Error",1,["bdk::wallet::coin_selection::Error"]],["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, Cs, Ctx> !RefUnwindSafe for TxBuilder<'a, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl RefUnwindSafe for AddUtxoError",1,["bdk::wallet::tx_builder::AddUtxoError"]],["impl RefUnwindSafe for AddForeignUtxoError",1,["bdk::wallet::tx_builder::AddForeignUtxoError"]],["impl RefUnwindSafe for AllowShrinkingError",1,["bdk::wallet::tx_builder::AllowShrinkingError"]],["impl RefUnwindSafe for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl RefUnwindSafe for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl RefUnwindSafe for MiniscriptPsbtError",1,["bdk::wallet::error::MiniscriptPsbtError"]],["impl !RefUnwindSafe for CreateTxError",1,["bdk::wallet::error::CreateTxError"]],["impl RefUnwindSafe for BuildFeeBumpError",1,["bdk::wallet::error::BuildFeeBumpError"]],["impl !RefUnwindSafe for Wallet",1,["bdk::wallet::Wallet"]],["impl RefUnwindSafe for Update",1,["bdk::wallet::Update"]],["impl RefUnwindSafe for ChangeSet",1,["bdk::wallet::ChangeSet"]],["impl RefUnwindSafe for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl !RefUnwindSafe for NewError",1,["bdk::wallet::NewError"]],["impl !RefUnwindSafe for LoadError",1,["bdk::wallet::LoadError"]],["impl !RefUnwindSafe for NewOrLoadError",1,["bdk::wallet::NewOrLoadError"]],["impl RefUnwindSafe for InsertTxError",1,["bdk::wallet::InsertTxError"]],["impl RefUnwindSafe for ApplyBlockError",1,["bdk::wallet::ApplyBlockError"]]], "bdk_bitcoind_rpc":[["impl<'c, C> RefUnwindSafe for Emitter<'c, C>where
    C: RefUnwindSafe,
",1,["bdk_bitcoind_rpc::Emitter"]],["impl<B> RefUnwindSafe for BlockEvent<B>where
    B: RefUnwindSafe,
",1,["bdk_bitcoind_rpc::BlockEvent"]]], "bdk_chain":[["impl<I> RefUnwindSafe for SpkTxOutIndex<I>where
    I: RefUnwindSafe,
",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl<A> RefUnwindSafe for ChainPosition<A>where
    A: RefUnwindSafe,
",1,["bdk_chain::chain_data::ChainPosition"]],["impl RefUnwindSafe for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl RefUnwindSafe for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl RefUnwindSafe for ConfirmationHeightAnchor",1,["bdk_chain::chain_data::ConfirmationHeightAnchor"]],["impl RefUnwindSafe for ConfirmationTimeHeightAnchor",1,["bdk_chain::chain_data::ConfirmationTimeHeightAnchor"]],["impl<A> RefUnwindSafe for FullTxOut<A>where
    A: RefUnwindSafe,
",1,["bdk_chain::chain_data::FullTxOut"]],["impl<A, I> RefUnwindSafe for IndexedTxGraph<A, I>where
    A: RefUnwindSafe,
    I: RefUnwindSafe,
",1,["bdk_chain::indexed_tx_graph::IndexedTxGraph"]],["impl<A, IA> RefUnwindSafe for ChangeSet<A, IA>where
    A: RefUnwindSafe,
    IA: RefUnwindSafe,
",1,["bdk_chain::indexed_tx_graph::ChangeSet"]],["impl<K> RefUnwindSafe for ChangeSet<K>where
    K: RefUnwindSafe,
",1,["bdk_chain::keychain::txout_index::ChangeSet"]],["impl<K> RefUnwindSafe for KeychainTxOutIndex<K>where
    K: RefUnwindSafe,
",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl RefUnwindSafe for Balance",1,["bdk_chain::keychain::Balance"]],["impl RefUnwindSafe for CheckPoint",1,["bdk_chain::local_chain::CheckPoint"]],["impl RefUnwindSafe for CheckPointIter",1,["bdk_chain::local_chain::CheckPointIter"]],["impl RefUnwindSafe for LocalChain",1,["bdk_chain::local_chain::LocalChain"]],["impl RefUnwindSafe for MissingGenesisError",1,["bdk_chain::local_chain::MissingGenesisError"]],["impl RefUnwindSafe for AlterCheckPointError",1,["bdk_chain::local_chain::AlterCheckPointError"]],["impl RefUnwindSafe for CannotConnectError",1,["bdk_chain::local_chain::CannotConnectError"]],["impl RefUnwindSafe for ApplyHeaderError",1,["bdk_chain::local_chain::ApplyHeaderError"]],["impl<A> RefUnwindSafe for TxGraph<A>where
    A: RefUnwindSafe,
",1,["bdk_chain::tx_graph::TxGraph"]],["impl<'a, T, A> RefUnwindSafe for TxNode<'a, T, A>where
    A: RefUnwindSafe,
    T: RefUnwindSafe,
",1,["bdk_chain::tx_graph::TxNode"]],["impl<'a, T, A> RefUnwindSafe for CanonicalTx<'a, T, A>where
    A: RefUnwindSafe,
    T: RefUnwindSafe,
",1,["bdk_chain::tx_graph::CanonicalTx"]],["impl RefUnwindSafe for CalculateFeeError",1,["bdk_chain::tx_graph::CalculateFeeError"]],["impl<A> RefUnwindSafe for ChangeSet<A>where
    A: RefUnwindSafe,
",1,["bdk_chain::tx_graph::ChangeSet"]],["impl<'g, A, F> RefUnwindSafe for TxAncestors<'g, A, F>where
    A: RefUnwindSafe,
    F: RefUnwindSafe,
",1,["bdk_chain::tx_graph::TxAncestors"]],["impl<'g, A, F> RefUnwindSafe for TxDescendants<'g, A, F>where
    A: RefUnwindSafe,
    F: RefUnwindSafe,
",1,["bdk_chain::tx_graph::TxDescendants"]],["impl RefUnwindSafe for DescriptorId",1,["bdk_chain::descriptor_ext::DescriptorId"]],["impl<D> RefUnwindSafe for SpkIterator<D>where
    D: RefUnwindSafe,
",1,["bdk_chain::spk_iter::SpkIterator"]],["impl !RefUnwindSafe for SyncRequest",1,["bdk_chain::spk_client::SyncRequest"]],["impl<A> RefUnwindSafe for SyncResult<A>where
    A: RefUnwindSafe,
",1,["bdk_chain::spk_client::SyncResult"]],["impl<K> !RefUnwindSafe for FullScanRequest<K>",1,["bdk_chain::spk_client::FullScanRequest"]],["impl<K, A> RefUnwindSafe for FullScanResult<K, A>where
    A: RefUnwindSafe,
    K: RefUnwindSafe,
",1,["bdk_chain::spk_client::FullScanResult"]]], "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"]]], @@ -9,6 +8,7 @@ "bdk_persist":[["impl<C> !RefUnwindSafe for Persist<C>",1,["bdk_persist::persist::Persist"]]], "bdk_testenv":[["impl !RefUnwindSafe for TestEnv",1,["bdk_testenv::TestEnv"]]], "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"]]], +"bdk_wallet":[["impl RefUnwindSafe for Error",1,["bdk_wallet::descriptor::error::Error"]],["impl RefUnwindSafe for PkOrF",1,["bdk_wallet::descriptor::policy::PkOrF"]],["impl RefUnwindSafe for SatisfiableItem",1,["bdk_wallet::descriptor::policy::SatisfiableItem"]],["impl RefUnwindSafe for Satisfaction",1,["bdk_wallet::descriptor::policy::Satisfaction"]],["impl RefUnwindSafe for Policy",1,["bdk_wallet::descriptor::policy::Policy"]],["impl RefUnwindSafe for Condition",1,["bdk_wallet::descriptor::policy::Condition"]],["impl RefUnwindSafe for PolicyError",1,["bdk_wallet::descriptor::policy::PolicyError"]],["impl<'a> RefUnwindSafe for BuildSatisfaction<'a>",1,["bdk_wallet::descriptor::policy::BuildSatisfaction"]],["impl<K> RefUnwindSafe for P2Pkh<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::P2Pkh"]],["impl<K> RefUnwindSafe for P2Wpkh_P2Sh<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> RefUnwindSafe for P2Wpkh<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::P2Wpkh"]],["impl<K> RefUnwindSafe for P2TR<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::P2TR"]],["impl<K> RefUnwindSafe for Bip44<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip44"]],["impl<K> RefUnwindSafe for Bip44Public<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip44Public"]],["impl<K> RefUnwindSafe for Bip49<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip49"]],["impl<K> RefUnwindSafe for Bip49Public<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip49Public"]],["impl<K> RefUnwindSafe for Bip84<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip84"]],["impl<K> RefUnwindSafe for Bip84Public<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip84Public"]],["impl<K> RefUnwindSafe for Bip86<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip86"]],["impl<K> RefUnwindSafe for Bip86Public<K>where
    K: RefUnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip86Public"]],["impl<Ctx> RefUnwindSafe for DescriptorKey<Ctx>where
    Ctx: RefUnwindSafe,
",1,["bdk_wallet::keys::DescriptorKey"]],["impl RefUnwindSafe for ScriptContextEnum",1,["bdk_wallet::keys::ScriptContextEnum"]],["impl<Ctx> RefUnwindSafe for ExtendedKey<Ctx>where
    Ctx: RefUnwindSafe,
",1,["bdk_wallet::keys::ExtendedKey"]],["impl<K, Ctx> RefUnwindSafe for GeneratedKey<K, Ctx>where
    Ctx: RefUnwindSafe,
    K: RefUnwindSafe,
",1,["bdk_wallet::keys::GeneratedKey"]],["impl RefUnwindSafe for PrivateKeyGenerateOptions",1,["bdk_wallet::keys::PrivateKeyGenerateOptions"]],["impl RefUnwindSafe for KeyError",1,["bdk_wallet::keys::KeyError"]],["impl RefUnwindSafe for KeychainKind",1,["bdk_wallet::types::KeychainKind"]],["impl RefUnwindSafe for LocalOutput",1,["bdk_wallet::types::LocalOutput"]],["impl RefUnwindSafe for WeightedUtxo",1,["bdk_wallet::types::WeightedUtxo"]],["impl RefUnwindSafe for Utxo",1,["bdk_wallet::types::Utxo"]],["impl RefUnwindSafe for Error",1,["bdk_wallet::wallet::coin_selection::Error"]],["impl RefUnwindSafe for Excess",1,["bdk_wallet::wallet::coin_selection::Excess"]],["impl RefUnwindSafe for CoinSelectionResult",1,["bdk_wallet::wallet::coin_selection::CoinSelectionResult"]],["impl RefUnwindSafe for LargestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::LargestFirstCoinSelection"]],["impl RefUnwindSafe for OldestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::OldestFirstCoinSelection"]],["impl RefUnwindSafe for BranchAndBoundCoinSelection",1,["bdk_wallet::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl RefUnwindSafe for FullyNodedExport",1,["bdk_wallet::wallet::export::FullyNodedExport"]],["impl RefUnwindSafe for SignerId",1,["bdk_wallet::wallet::signer::SignerId"]],["impl RefUnwindSafe for SignerError",1,["bdk_wallet::wallet::signer::SignerError"]],["impl RefUnwindSafe for SignerContext",1,["bdk_wallet::wallet::signer::SignerContext"]],["impl<S> RefUnwindSafe for SignerWrapper<S>where
    S: RefUnwindSafe,
",1,["bdk_wallet::wallet::signer::SignerWrapper"]],["impl RefUnwindSafe for SignerOrdering",1,["bdk_wallet::wallet::signer::SignerOrdering"]],["impl !RefUnwindSafe for SignersContainer",1,["bdk_wallet::wallet::signer::SignersContainer"]],["impl RefUnwindSafe for SignOptions",1,["bdk_wallet::wallet::signer::SignOptions"]],["impl RefUnwindSafe for TapLeavesOptions",1,["bdk_wallet::wallet::signer::TapLeavesOptions"]],["impl RefUnwindSafe for CreateTx",1,["bdk_wallet::wallet::tx_builder::CreateTx"]],["impl RefUnwindSafe for BumpFee",1,["bdk_wallet::wallet::tx_builder::BumpFee"]],["impl<'a, Cs, Ctx> !RefUnwindSafe for TxBuilder<'a, Cs, Ctx>",1,["bdk_wallet::wallet::tx_builder::TxBuilder"]],["impl RefUnwindSafe for AddUtxoError",1,["bdk_wallet::wallet::tx_builder::AddUtxoError"]],["impl RefUnwindSafe for AddForeignUtxoError",1,["bdk_wallet::wallet::tx_builder::AddForeignUtxoError"]],["impl RefUnwindSafe for AllowShrinkingError",1,["bdk_wallet::wallet::tx_builder::AllowShrinkingError"]],["impl RefUnwindSafe for TxOrdering",1,["bdk_wallet::wallet::tx_builder::TxOrdering"]],["impl RefUnwindSafe for ChangeSpendPolicy",1,["bdk_wallet::wallet::tx_builder::ChangeSpendPolicy"]],["impl RefUnwindSafe for MiniscriptPsbtError",1,["bdk_wallet::wallet::error::MiniscriptPsbtError"]],["impl !RefUnwindSafe for CreateTxError",1,["bdk_wallet::wallet::error::CreateTxError"]],["impl RefUnwindSafe for BuildFeeBumpError",1,["bdk_wallet::wallet::error::BuildFeeBumpError"]],["impl !RefUnwindSafe for Wallet",1,["bdk_wallet::wallet::Wallet"]],["impl RefUnwindSafe for Update",1,["bdk_wallet::wallet::Update"]],["impl RefUnwindSafe for ChangeSet",1,["bdk_wallet::wallet::ChangeSet"]],["impl RefUnwindSafe for AddressInfo",1,["bdk_wallet::wallet::AddressInfo"]],["impl !RefUnwindSafe for NewError",1,["bdk_wallet::wallet::NewError"]],["impl !RefUnwindSafe for LoadError",1,["bdk_wallet::wallet::LoadError"]],["impl !RefUnwindSafe for NewOrLoadError",1,["bdk_wallet::wallet::NewOrLoadError"]],["impl RefUnwindSafe for InsertTxError",1,["bdk_wallet::wallet::InsertTxError"]],["impl RefUnwindSafe for ApplyBlockError",1,["bdk_wallet::wallet::ApplyBlockError"]]], "example_bitcoind_rpc_polling":[["impl RefUnwindSafe for Emission",1,["example_bitcoind_rpc_polling::Emission"]],["impl RefUnwindSafe for RpcArgs",1,["example_bitcoind_rpc_polling::RpcArgs"]],["impl RefUnwindSafe for RpcCommands",1,["example_bitcoind_rpc_polling::RpcCommands"]]], "example_cli":[["impl<CS, S> RefUnwindSafe for Args<CS, S>where
    CS: RefUnwindSafe,
    S: RefUnwindSafe,
",1,["example_cli::Args"]],["impl<CS, S> RefUnwindSafe for Commands<CS, S>where
    CS: RefUnwindSafe,
    S: RefUnwindSafe,
",1,["example_cli::Commands"]],["impl RefUnwindSafe for CoinSelectionAlgo",1,["example_cli::CoinSelectionAlgo"]],["impl RefUnwindSafe for AddressCmd",1,["example_cli::AddressCmd"]],["impl RefUnwindSafe for TxOutCmd",1,["example_cli::TxOutCmd"]],["impl RefUnwindSafe for Keychain",1,["example_cli::Keychain"]],["impl RefUnwindSafe for CreateTxChange",1,["example_cli::CreateTxChange"]],["impl<CS, S, C> RefUnwindSafe for Init<CS, S, C>where
    C: RefUnwindSafe,
    CS: RefUnwindSafe,
    S: RefUnwindSafe,
",1,["example_cli::Init"]]], "example_electrum":[["impl RefUnwindSafe for ElectrumCommands",1,["example_electrum::ElectrumCommands"]],["impl RefUnwindSafe for ElectrumArgs",1,["example_electrum::ElectrumArgs"]],["impl RefUnwindSafe for ScanOptions",1,["example_electrum::ScanOptions"]]], 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 7185f1a93b..8de9f84e7b 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,5 +1,4 @@ (function() {var implementors = { -"bdk":[["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 P2TR<K>where
    K: UnwindSafe,
",1,["bdk::descriptor::template::P2TR"]],["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<K> UnwindSafe for Bip86<K>where
    K: UnwindSafe,
",1,["bdk::descriptor::template::Bip86"]],["impl<K> UnwindSafe for Bip86Public<K>where
    K: UnwindSafe,
",1,["bdk::descriptor::template::Bip86Public"]],["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 LocalOutput",1,["bdk::types::LocalOutput"]],["impl UnwindSafe for WeightedUtxo",1,["bdk::types::WeightedUtxo"]],["impl UnwindSafe for Utxo",1,["bdk::types::Utxo"]],["impl UnwindSafe for Error",1,["bdk::wallet::coin_selection::Error"]],["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, Cs, Ctx> !UnwindSafe for TxBuilder<'a, Cs, Ctx>",1,["bdk::wallet::tx_builder::TxBuilder"]],["impl UnwindSafe for AddUtxoError",1,["bdk::wallet::tx_builder::AddUtxoError"]],["impl UnwindSafe for AddForeignUtxoError",1,["bdk::wallet::tx_builder::AddForeignUtxoError"]],["impl UnwindSafe for AllowShrinkingError",1,["bdk::wallet::tx_builder::AllowShrinkingError"]],["impl UnwindSafe for TxOrdering",1,["bdk::wallet::tx_builder::TxOrdering"]],["impl UnwindSafe for ChangeSpendPolicy",1,["bdk::wallet::tx_builder::ChangeSpendPolicy"]],["impl UnwindSafe for MiniscriptPsbtError",1,["bdk::wallet::error::MiniscriptPsbtError"]],["impl !UnwindSafe for CreateTxError",1,["bdk::wallet::error::CreateTxError"]],["impl UnwindSafe for BuildFeeBumpError",1,["bdk::wallet::error::BuildFeeBumpError"]],["impl !UnwindSafe for Wallet",1,["bdk::wallet::Wallet"]],["impl UnwindSafe for Update",1,["bdk::wallet::Update"]],["impl UnwindSafe for ChangeSet",1,["bdk::wallet::ChangeSet"]],["impl UnwindSafe for AddressInfo",1,["bdk::wallet::AddressInfo"]],["impl !UnwindSafe for NewError",1,["bdk::wallet::NewError"]],["impl !UnwindSafe for LoadError",1,["bdk::wallet::LoadError"]],["impl !UnwindSafe for NewOrLoadError",1,["bdk::wallet::NewOrLoadError"]],["impl UnwindSafe for InsertTxError",1,["bdk::wallet::InsertTxError"]],["impl UnwindSafe for ApplyBlockError",1,["bdk::wallet::ApplyBlockError"]]], "bdk_bitcoind_rpc":[["impl<'c, C> UnwindSafe for Emitter<'c, C>where
    C: RefUnwindSafe,
",1,["bdk_bitcoind_rpc::Emitter"]],["impl<B> UnwindSafe for BlockEvent<B>where
    B: UnwindSafe,
",1,["bdk_bitcoind_rpc::BlockEvent"]]], "bdk_chain":[["impl<I> UnwindSafe for SpkTxOutIndex<I>where
    I: UnwindSafe + RefUnwindSafe,
",1,["bdk_chain::spk_txout_index::SpkTxOutIndex"]],["impl<A> UnwindSafe for ChainPosition<A>where
    A: UnwindSafe,
",1,["bdk_chain::chain_data::ChainPosition"]],["impl UnwindSafe for ConfirmationTime",1,["bdk_chain::chain_data::ConfirmationTime"]],["impl UnwindSafe for BlockId",1,["bdk_chain::chain_data::BlockId"]],["impl UnwindSafe for ConfirmationHeightAnchor",1,["bdk_chain::chain_data::ConfirmationHeightAnchor"]],["impl UnwindSafe for ConfirmationTimeHeightAnchor",1,["bdk_chain::chain_data::ConfirmationTimeHeightAnchor"]],["impl<A> UnwindSafe for FullTxOut<A>where
    A: UnwindSafe,
",1,["bdk_chain::chain_data::FullTxOut"]],["impl<A, I> UnwindSafe for IndexedTxGraph<A, I>where
    A: RefUnwindSafe,
    I: UnwindSafe,
",1,["bdk_chain::indexed_tx_graph::IndexedTxGraph"]],["impl<A, IA> UnwindSafe for ChangeSet<A, IA>where
    A: RefUnwindSafe,
    IA: UnwindSafe,
",1,["bdk_chain::indexed_tx_graph::ChangeSet"]],["impl<K> UnwindSafe for ChangeSet<K>where
    K: RefUnwindSafe,
",1,["bdk_chain::keychain::txout_index::ChangeSet"]],["impl<K> UnwindSafe for KeychainTxOutIndex<K>where
    K: RefUnwindSafe,
",1,["bdk_chain::keychain::txout_index::KeychainTxOutIndex"]],["impl UnwindSafe for Balance",1,["bdk_chain::keychain::Balance"]],["impl UnwindSafe for CheckPoint",1,["bdk_chain::local_chain::CheckPoint"]],["impl UnwindSafe for CheckPointIter",1,["bdk_chain::local_chain::CheckPointIter"]],["impl UnwindSafe for LocalChain",1,["bdk_chain::local_chain::LocalChain"]],["impl UnwindSafe for MissingGenesisError",1,["bdk_chain::local_chain::MissingGenesisError"]],["impl UnwindSafe for AlterCheckPointError",1,["bdk_chain::local_chain::AlterCheckPointError"]],["impl UnwindSafe for CannotConnectError",1,["bdk_chain::local_chain::CannotConnectError"]],["impl UnwindSafe for ApplyHeaderError",1,["bdk_chain::local_chain::ApplyHeaderError"]],["impl<A> UnwindSafe for TxGraph<A>where
    A: RefUnwindSafe,
",1,["bdk_chain::tx_graph::TxGraph"]],["impl<'a, T, A> UnwindSafe for TxNode<'a, T, A>where
    A: RefUnwindSafe,
    T: UnwindSafe,
",1,["bdk_chain::tx_graph::TxNode"]],["impl<'a, T, A> UnwindSafe for CanonicalTx<'a, T, A>where
    A: RefUnwindSafe,
    T: UnwindSafe,
",1,["bdk_chain::tx_graph::CanonicalTx"]],["impl UnwindSafe for CalculateFeeError",1,["bdk_chain::tx_graph::CalculateFeeError"]],["impl<A> UnwindSafe for ChangeSet<A>where
    A: RefUnwindSafe,
",1,["bdk_chain::tx_graph::ChangeSet"]],["impl<'g, A, F> UnwindSafe for TxAncestors<'g, A, F>where
    A: RefUnwindSafe,
    F: UnwindSafe,
",1,["bdk_chain::tx_graph::TxAncestors"]],["impl<'g, A, F> UnwindSafe for TxDescendants<'g, A, F>where
    A: RefUnwindSafe,
    F: UnwindSafe,
",1,["bdk_chain::tx_graph::TxDescendants"]],["impl UnwindSafe for DescriptorId",1,["bdk_chain::descriptor_ext::DescriptorId"]],["impl<D> UnwindSafe for SpkIterator<D>where
    D: UnwindSafe,
",1,["bdk_chain::spk_iter::SpkIterator"]],["impl !UnwindSafe for SyncRequest",1,["bdk_chain::spk_client::SyncRequest"]],["impl<A> UnwindSafe for SyncResult<A>where
    A: RefUnwindSafe,
",1,["bdk_chain::spk_client::SyncResult"]],["impl<K> !UnwindSafe for FullScanRequest<K>",1,["bdk_chain::spk_client::FullScanRequest"]],["impl<K, A> UnwindSafe for FullScanResult<K, A>where
    A: RefUnwindSafe,
    K: RefUnwindSafe,
",1,["bdk_chain::spk_client::FullScanResult"]]], "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"]]], @@ -9,6 +8,7 @@ "bdk_persist":[["impl<C> !UnwindSafe for Persist<C>",1,["bdk_persist::persist::Persist"]]], "bdk_testenv":[["impl !UnwindSafe for TestEnv",1,["bdk_testenv::TestEnv"]]], "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"]]], +"bdk_wallet":[["impl UnwindSafe for Error",1,["bdk_wallet::descriptor::error::Error"]],["impl UnwindSafe for PkOrF",1,["bdk_wallet::descriptor::policy::PkOrF"]],["impl UnwindSafe for SatisfiableItem",1,["bdk_wallet::descriptor::policy::SatisfiableItem"]],["impl UnwindSafe for Satisfaction",1,["bdk_wallet::descriptor::policy::Satisfaction"]],["impl UnwindSafe for Policy",1,["bdk_wallet::descriptor::policy::Policy"]],["impl UnwindSafe for Condition",1,["bdk_wallet::descriptor::policy::Condition"]],["impl UnwindSafe for PolicyError",1,["bdk_wallet::descriptor::policy::PolicyError"]],["impl<'a> UnwindSafe for BuildSatisfaction<'a>",1,["bdk_wallet::descriptor::policy::BuildSatisfaction"]],["impl<K> UnwindSafe for P2Pkh<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::P2Pkh"]],["impl<K> UnwindSafe for P2Wpkh_P2Sh<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::P2Wpkh_P2Sh"]],["impl<K> UnwindSafe for P2Wpkh<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::P2Wpkh"]],["impl<K> UnwindSafe for P2TR<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::P2TR"]],["impl<K> UnwindSafe for Bip44<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip44"]],["impl<K> UnwindSafe for Bip44Public<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip44Public"]],["impl<K> UnwindSafe for Bip49<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip49"]],["impl<K> UnwindSafe for Bip49Public<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip49Public"]],["impl<K> UnwindSafe for Bip84<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip84"]],["impl<K> UnwindSafe for Bip84Public<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip84Public"]],["impl<K> UnwindSafe for Bip86<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip86"]],["impl<K> UnwindSafe for Bip86Public<K>where
    K: UnwindSafe,
",1,["bdk_wallet::descriptor::template::Bip86Public"]],["impl<Ctx> UnwindSafe for DescriptorKey<Ctx>where
    Ctx: UnwindSafe,
",1,["bdk_wallet::keys::DescriptorKey"]],["impl UnwindSafe for ScriptContextEnum",1,["bdk_wallet::keys::ScriptContextEnum"]],["impl<Ctx> UnwindSafe for ExtendedKey<Ctx>where
    Ctx: UnwindSafe,
",1,["bdk_wallet::keys::ExtendedKey"]],["impl<K, Ctx> UnwindSafe for GeneratedKey<K, Ctx>where
    Ctx: UnwindSafe,
    K: UnwindSafe,
",1,["bdk_wallet::keys::GeneratedKey"]],["impl UnwindSafe for PrivateKeyGenerateOptions",1,["bdk_wallet::keys::PrivateKeyGenerateOptions"]],["impl UnwindSafe for KeyError",1,["bdk_wallet::keys::KeyError"]],["impl UnwindSafe for KeychainKind",1,["bdk_wallet::types::KeychainKind"]],["impl UnwindSafe for LocalOutput",1,["bdk_wallet::types::LocalOutput"]],["impl UnwindSafe for WeightedUtxo",1,["bdk_wallet::types::WeightedUtxo"]],["impl UnwindSafe for Utxo",1,["bdk_wallet::types::Utxo"]],["impl UnwindSafe for Error",1,["bdk_wallet::wallet::coin_selection::Error"]],["impl UnwindSafe for Excess",1,["bdk_wallet::wallet::coin_selection::Excess"]],["impl UnwindSafe for CoinSelectionResult",1,["bdk_wallet::wallet::coin_selection::CoinSelectionResult"]],["impl UnwindSafe for LargestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::LargestFirstCoinSelection"]],["impl UnwindSafe for OldestFirstCoinSelection",1,["bdk_wallet::wallet::coin_selection::OldestFirstCoinSelection"]],["impl UnwindSafe for BranchAndBoundCoinSelection",1,["bdk_wallet::wallet::coin_selection::BranchAndBoundCoinSelection"]],["impl UnwindSafe for FullyNodedExport",1,["bdk_wallet::wallet::export::FullyNodedExport"]],["impl UnwindSafe for SignerId",1,["bdk_wallet::wallet::signer::SignerId"]],["impl UnwindSafe for SignerError",1,["bdk_wallet::wallet::signer::SignerError"]],["impl UnwindSafe for SignerContext",1,["bdk_wallet::wallet::signer::SignerContext"]],["impl<S> UnwindSafe for SignerWrapper<S>where
    S: UnwindSafe,
",1,["bdk_wallet::wallet::signer::SignerWrapper"]],["impl UnwindSafe for SignerOrdering",1,["bdk_wallet::wallet::signer::SignerOrdering"]],["impl !UnwindSafe for SignersContainer",1,["bdk_wallet::wallet::signer::SignersContainer"]],["impl UnwindSafe for SignOptions",1,["bdk_wallet::wallet::signer::SignOptions"]],["impl UnwindSafe for TapLeavesOptions",1,["bdk_wallet::wallet::signer::TapLeavesOptions"]],["impl UnwindSafe for CreateTx",1,["bdk_wallet::wallet::tx_builder::CreateTx"]],["impl UnwindSafe for BumpFee",1,["bdk_wallet::wallet::tx_builder::BumpFee"]],["impl<'a, Cs, Ctx> !UnwindSafe for TxBuilder<'a, Cs, Ctx>",1,["bdk_wallet::wallet::tx_builder::TxBuilder"]],["impl UnwindSafe for AddUtxoError",1,["bdk_wallet::wallet::tx_builder::AddUtxoError"]],["impl UnwindSafe for AddForeignUtxoError",1,["bdk_wallet::wallet::tx_builder::AddForeignUtxoError"]],["impl UnwindSafe for AllowShrinkingError",1,["bdk_wallet::wallet::tx_builder::AllowShrinkingError"]],["impl UnwindSafe for TxOrdering",1,["bdk_wallet::wallet::tx_builder::TxOrdering"]],["impl UnwindSafe for ChangeSpendPolicy",1,["bdk_wallet::wallet::tx_builder::ChangeSpendPolicy"]],["impl UnwindSafe for MiniscriptPsbtError",1,["bdk_wallet::wallet::error::MiniscriptPsbtError"]],["impl !UnwindSafe for CreateTxError",1,["bdk_wallet::wallet::error::CreateTxError"]],["impl UnwindSafe for BuildFeeBumpError",1,["bdk_wallet::wallet::error::BuildFeeBumpError"]],["impl !UnwindSafe for Wallet",1,["bdk_wallet::wallet::Wallet"]],["impl UnwindSafe for Update",1,["bdk_wallet::wallet::Update"]],["impl UnwindSafe for ChangeSet",1,["bdk_wallet::wallet::ChangeSet"]],["impl UnwindSafe for AddressInfo",1,["bdk_wallet::wallet::AddressInfo"]],["impl !UnwindSafe for NewError",1,["bdk_wallet::wallet::NewError"]],["impl !UnwindSafe for LoadError",1,["bdk_wallet::wallet::LoadError"]],["impl !UnwindSafe for NewOrLoadError",1,["bdk_wallet::wallet::NewOrLoadError"]],["impl UnwindSafe for InsertTxError",1,["bdk_wallet::wallet::InsertTxError"]],["impl UnwindSafe for ApplyBlockError",1,["bdk_wallet::wallet::ApplyBlockError"]]], "example_bitcoind_rpc_polling":[["impl UnwindSafe for Emission",1,["example_bitcoind_rpc_polling::Emission"]],["impl UnwindSafe for RpcArgs",1,["example_bitcoind_rpc_polling::RpcArgs"]],["impl UnwindSafe for RpcCommands",1,["example_bitcoind_rpc_polling::RpcCommands"]]], "example_cli":[["impl<CS, S> UnwindSafe for Args<CS, S>where
    CS: UnwindSafe,
    S: UnwindSafe,
",1,["example_cli::Args"]],["impl<CS, S> UnwindSafe for Commands<CS, S>where
    CS: UnwindSafe,
    S: UnwindSafe,
",1,["example_cli::Commands"]],["impl UnwindSafe for CoinSelectionAlgo",1,["example_cli::CoinSelectionAlgo"]],["impl UnwindSafe for AddressCmd",1,["example_cli::AddressCmd"]],["impl UnwindSafe for TxOutCmd",1,["example_cli::TxOutCmd"]],["impl UnwindSafe for Keychain",1,["example_cli::Keychain"]],["impl UnwindSafe for CreateTxChange",1,["example_cli::CreateTxChange"]],["impl<CS, S, C> UnwindSafe for Init<CS, S, C>where
    C: UnwindSafe,
    CS: UnwindSafe,
    S: UnwindSafe,
",1,["example_cli::Init"]]], "example_electrum":[["impl UnwindSafe for ElectrumCommands",1,["example_electrum::ElectrumCommands"]],["impl UnwindSafe for ElectrumArgs",1,["example_electrum::ElectrumArgs"]],["impl UnwindSafe for ScanOptions",1,["example_electrum::ScanOptions"]]], 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 0700517520..a5a57a000b 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,5 +1,5 @@ (function() {var implementors = { -"bdk":[["impl FromStr for FullyNodedExport"]], "bdk_chain":[["impl FromStr for DescriptorId"]], +"bdk_wallet":[["impl FromStr for FullyNodedExport"]], "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/miniscript/miniscript/context/trait.ScriptContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/miniscript/miniscript/context/trait.ScriptContext.js index bb0690bde5..e69e7865df 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/miniscript/miniscript/context/trait.ScriptContext.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/miniscript/miniscript/context/trait.ScriptContext.js @@ -1,3 +1,3 @@ (function() {var implementors = { -"bdk":[] +"bdk_wallet":[] };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 f2696e5cfd..0f5cca554f 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,5 +1,5 @@ (function() {var implementors = { -"bdk":[["impl<'de> Deserialize<'de> for KeychainKind"],["impl<'de> Deserialize<'de> for LocalOutput"],["impl<'de> Deserialize<'de> for FullyNodedExport"],["impl<'de> Deserialize<'de> for ChangeSet"]], "bdk_chain":[["impl<'de> Deserialize<'de> for ConfirmationTime"],["impl<'de> Deserialize<'de> for BlockId"],["impl<'de> Deserialize<'de> for ConfirmationHeightAnchor"],["impl<'de> Deserialize<'de> for ConfirmationTimeHeightAnchor"],["impl<'de, A, IA> Deserialize<'de> for ChangeSet<A, IA>where
    A: Ord + Deserialize<'de>,
    IA: Deserialize<'de>,
"],["impl<'de, K> Deserialize<'de> for ChangeSet<K>where
    K: Ord + Deserialize<'de>,
"],["impl<'de> Deserialize<'de> for Balance"],["impl<'de, A> Deserialize<'de> for ChangeSet<A>where
    A: Ord + Deserialize<'de>,
"],["impl<'de> Deserialize<'de> for DescriptorId"]], +"bdk_wallet":[["impl<'de> Deserialize<'de> for KeychainKind"],["impl<'de> Deserialize<'de> for LocalOutput"],["impl<'de> Deserialize<'de> for FullyNodedExport"],["impl<'de> Deserialize<'de> for ChangeSet"]], "example_cli":[["impl<'de> Deserialize<'de> 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/serde/ser/trait.Serialize.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/ser/trait.Serialize.js index 66b5354d9a..39627f1a6a 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,5 +1,5 @@ (function() {var implementors = { -"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 LocalOutput"],["impl Serialize for FullyNodedExport"],["impl Serialize for ChangeSet"]], "bdk_chain":[["impl Serialize for ConfirmationTime"],["impl Serialize for BlockId"],["impl Serialize for ConfirmationHeightAnchor"],["impl Serialize for ConfirmationTimeHeightAnchor"],["impl<A, IA> Serialize for ChangeSet<A, IA>where
    A: Ord + Serialize,
    IA: Serialize,
"],["impl<K> Serialize for ChangeSet<K>where
    K: Ord + Serialize,
"],["impl Serialize for Balance"],["impl<A> Serialize for ChangeSet<A>where
    A: Ord + Serialize,
"],["impl Serialize for DescriptorId"]], +"bdk_wallet":[["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 LocalOutput"],["impl Serialize for FullyNodedExport"],["impl Serialize for ChangeSet"]], "example_cli":[["impl Serialize 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/search-index.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/search-index.js index 1620112b6b..ce49199280 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,4 @@ var searchIndex = JSON.parse('{\ -"bdk":{"doc":"bdk","t":[13,13,2,13,4,13,3,2,2,4,2,3,11,11,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,12,12,0,14,11,11,11,11,11,11,11,11,11,11,14,11,11,11,11,11,11,11,11,11,11,12,12,0,11,12,11,0,12,11,11,11,2,2,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,12,5,11,11,11,11,0,12,12,12,13,6,4,2,4,6,8,6,8,16,4,3,13,13,2,8,4,13,13,6,13,13,13,13,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,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,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,10,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,11,11,12,11,11,11,11,11,11,11,11,11,10,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,10,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,5,5,13,13,4,13,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,3,3,8,6,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,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,13,8,4,4,4,16,16,8,4,13,8,8,3,8,13,13,13,16,4,6,13,13,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,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,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,10,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,11,11,11,11,12,12,12,11,5,11,10,11,11,5,10,11,11,12,12,11,11,11,11,11,11,10,12,11,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,11,11,8,10,10,10,3,4,3,13,3,13,13,13,13,4,8,4,13,13,13,13,13,13,4,4,13,13,13,13,13,13,13,3,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,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,0,11,12,11,11,11,11,11,11,11,11,11,11,11,11,0,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,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,12,11,12,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,0,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,0,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,5,12,12,12,12,12,12,12,12,12,12,13,13,3,13,8,3,6,4,4,13,3,13,3,11,11,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,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,12,12,12,12,12,12,12,4,13,13,13,4,13,13,13,13,13,13,13,13,4,13,13,13,13,13,13,13,13,13,13,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,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,3,6,12,11,11,11,11,11,11,11,11,11,11,11,12,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,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,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,10,11,11,11,10,11,12,11,12,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,4,4,4,13,3,13,13,4,3,13,13,13,13,13,13,3,8,4,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,11,11,11,11,11,11,11,11,11,11,11,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],"n":["External","Foreign","HdKeyPaths","Internal","KeychainKind","Local","LocalOutput","SignOptions","TxBuilder","Utxo","Wallet","WeightedUtxo","as_byte","as_ref","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","chain","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","confirmation_time","derivation_index","descriptor","descriptor","deserialize","deserialize","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fragment","from","from","from","from","hash","hash","into","into","into","into","is_spent","keychain","keys","outpoint","outpoint","partial_cmp","psbt","satisfaction_weight","sequence","serialize","serialize","signer","template","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","txout","txout","type_id","type_id","type_id","type_id","utxo","version","vzip","vzip","vzip","vzip","wallet","outpoint","psbt_input","sequence","Bare","DerivedDescriptor","Descriptor","DescriptorError","DescriptorPublicKey","ExtendedDescriptor","ExtractPolicy","HdKeyPaths","IntoWalletDescriptor","Key","Legacy","Miniscript","MultiXPub","Pkh","Policy","ScriptContext","Segwitv0","Sh","Single","TapKeyOrigins","Tr","Wpkh","Wsh","XPub","address","as_enum","as_enum","as_inner","as_node","at_derivation_index","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","branches","build_template","build_template_mall","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_pk","check_pk","check_pk","check_terminal_non_malleable","check_terminal_non_malleable","check_terminal_non_malleable","check_witness","check_witness","check_witness","checksum","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","contains_raw_pkh","derive","derived_descriptor","derived_descriptor","desc_type","descriptor_id","deserialize","deserialize","dust_value","encode","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","for_each_key","for_each_key","from","from","from","from","from","from","from","from","from","from","from_ast","from_components_unchecked","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","into","into","into","into","into_inner","into_single_descriptors","into_wallet_descriptor","into_wallet_descriptor","is_deriveable","is_multipath","is_non_malleable","iter","iter_pk","lift","lift","lift_check","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_weight","max_satisfaction_witness_elements","max_weight_to_satisfy","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","other_top_level_checks","parse","parse_descriptor","parse_insane","parse_with_ext","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pk_len","pk_len","plan","plan_mall","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","substitute_raw_pkh","template","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_into","try_into","try_into","try_into","ty","type_id","type_id","type_id","type_id","unsigned_script_sig","vzip","vzip","vzip","vzip","within_resource_limits","calc_checksum","calc_checksum_bytes","Base58","Bip32","Error","HardenedDerivationXpub","Hex","InvalidDescriptorCharacter","InvalidDescriptorChecksum","InvalidHdKeyPath","Key","Miniscript","MultiPath","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","Bip86","Bip86Public","DescriptorTemplate","DescriptorTemplateOut","P2Pkh","P2TR","P2Wpkh","P2Wpkh_P2Sh","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","build","build","build","build","build","build","build","build","build","build","build","build","build","from","from","from","from","from","from","from","from","from","from","from","from","into","into","into","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","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_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","Bip32","DerivableKey","DescriptorKey","DescriptorPublicKey","DescriptorSecretKey","Entropy","Error","ExtScriptContext","ExtendedKey","FullKey","GeneratableDefaultOptions","GeneratableKey","GeneratedKey","IntoDescriptorKey","InvalidChecksum","InvalidNetwork","InvalidScriptContext","Key","KeyError","KeyMap","Legacy","Message","Miniscript","MultiXPrv","MultiXPub","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","build_template","check_global_consensus_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_policy_validity","check_local_validity","check_pk","check_terminal_non_malleable","check_witness","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","compressed","default","deref","derive","deserialize","encode","eq","eq","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","full_derivation_paths","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_assets","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_single_keys","into_single_keys","into_xprv","into_xpub","is_deriveable","is_legacy","is_legacy","is_multipath","is_multipath","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","num_der_paths","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","serialize","sig_type","sorted_node","test_networks","to_owned","to_owned","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","AddressInfo","ApplyBlockError","Balance","CannotConnect","ChangeSet","ConfirmationHeightCannotBeGreaterThanTip","Descriptor","Descriptor","Descriptor","InsertTxError","IsDust","LoadError","LoadedDescriptorDoesNotMatch","LoadedGenesisDoesNotMatch","LoadedNetworkDoesNotMatch","MissingDescriptor","MissingGenesis","MissingNetwork","NewError","NewOrLoadError","NonEmptyDatabase","NotInitialized","NotInitialized","Persist","Persist","Persist","UnexpectedConnectedToHash","Update","Wallet","add","add_signer","address","all_unbounded_spk_iters","append","apply_block","apply_block_connected_to","apply_unconfirmed_txs","apply_update","as_ref","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","build_fee_bump","build_tx","calculate_fee","calculate_fee_rate","cancel_tx","chain","chain","checkpoints","clone","clone","clone","clone_into","clone_into","clone_into","coin_selection","commit","confirmed","default","default","default","deref","derivation_index","derivation_of_spk","descriptor_checksum","deserialize","deserialize","eq","eq","eq","error","export","finalize_psbt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","get_balance","get_descriptor_for_keychain","get_psbt_input","get_signers","get_tx","get_utxo","graph","immature","index","indexed_tx_graph","insert_checkpoint","insert_tx","insert_txout","into","into","into","into","into","into","into","into","into","into","is_dust","is_empty","is_mine","keychain","keychains","last_active_indices","latest_checkpoint","list_output","list_unspent","list_unused_addresses","load","local_chain","mark_used","network","network","new","new_no_persist","new_no_persist_with_genesis_hash","new_or_load","new_or_load_with_genesis_hash","new_with_genesis_hash","next_derivation_index","next_unused_address","peek_address","policies","provide","provide","provide","provide","provide","public_descriptor","reveal_addresses_to","reveal_next_address","secp_ctx","sent_and_received","serialize","serialize","sign","signer","spk_index","staged","start_full_scan","start_sync_with_revealed_spks","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","to_string","to_string","total","transactions","trusted_pending","trusted_spendable","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","tx_builder","tx_graph","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unbounded_spk_iter","unmark_used","untrusted_pending","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","wallet_name_from_descriptor","connected_to_hash","expected_hash","tip_height","tx_height","expected","expected","got","got","got","keychain","BnBNoExactMatch","BnBTotalTriesExceeded","BranchAndBoundCoinSelection","Change","CoinSelectionAlgorithm","CoinSelectionResult","DefaultCoinSelectionAlgorithm","Error","Excess","InsufficientFunds","LargestFirstCoinSelection","NoChange","OldestFirstCoinSelection","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","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","fmt","fmt","from","from","from","from","from","from","into","into","into","into","into","into","local_selected_amount","new","provide","selected","selected_amount","to_owned","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","available","needed","amount","change_fee","dust_threshold","fee","remaining_amount","BuildFeeBumpError","ChangePolicyDescriptor","CoinSelection","Conversion","CreateTxError","Descriptor","FeeRateTooLow","FeeRateUnavailable","FeeTooLow","InsufficientFunds","IrreplaceableTransaction","LockTime","MiniscriptPsbt","MiniscriptPsbtError","MissingKeyOrigin","MissingNonWitnessUtxo","NoRecipients","NoUtxosSelected","OutputBelowDustLimit","OutputUpdate","Persist","Policy","Psbt","RbfSequence","RbfSequenceCsv","SpendingPolicyRequired","TransactionConfirmed","TransactionNotFound","UnknownUtxo","UnknownUtxo","UtxoUpdate","Version0","Version1Csv","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","into","into","into","provide","provide","provide","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","vzip","vzip","vzip","available","csv","needed","rbf","requested","required","required","required","FullyNodedExport","WalletExport","blockheight","borrow","borrow_mut","change_descriptor","descriptor","deserialize","export_wallet","fmt","fmt","from","from_str","into","label","serialize","to_string","try_from","try_into","type_id","vzip","All","Dummy","Exclude","External","Fingerprint","Include","InputIndexOutOfRange","InputSigner","InvalidKey","InvalidNonWitnessUtxo","InvalidSighash","Legacy","MiniscriptPsbt","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_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","descriptor_secret_key","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","id","ids","into","into","into","into","into","into","into","into","new","new","partial_cmp","partial_cmp","provide","remove","remove_partial_sigs","remove_taproot_extras","sign_input","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_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","AddForeignUtxoError","AddUtxoError","AllowShrinkingError","Bip69Lexicographic","BumpFee","ChangeAllowed","ChangeForbidden","ChangeSpendPolicy","CreateTx","InvalidOutpoint","InvalidTxid","MissingScriptPubKey","MissingUtxo","OnlyChange","Shuffle","TxBuilder","TxBuilderContext","TxOrdering","UnknownUtxo","Untouched","add_data","add_foreign_utxo","add_foreign_utxo_with_sequence","add_global_xpubs","add_recipient","add_unspendable","add_utxo","add_utxos","allow_dust","allow_shrinking","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","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","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","hash","hash","include_output_redeem_witness_script","into","into","into","into","into","into","into","into","manually_selected_only","nlocktime","only_spend_change","only_witness_utxo","ordering","partial_cmp","partial_cmp","policy_path","provide","provide","provide","set_recipients","sighash","sort_tx","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_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","unspendable","version","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","foreign_utxo","input_txid"],"q":["bdk","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","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::ApplyBlockError","","bdk::wallet::InsertTxError","","bdk::wallet::NewOrLoadError","","","","","","bdk::wallet::coin_selection","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::coin_selection::Error","","bdk::wallet::coin_selection::Excess","","","","","bdk::wallet::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::error::CreateTxError","","","","","","","","bdk::wallet::export","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer::SignerContext","bdk::wallet::tx_builder","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::tx_builder::AddForeignUtxoError",""],"d":["External keychain, used for deriving recipient addresses.","A UTXO owned by another wallet.","","Internal keychain, used for deriving change addresses.","Types of keychains","A UTXO owned by the local wallet.","An unspent output owned by a Wallet.","","","An unspent transaction output (UTXO).","","A Utxo with its satisfaction_weight.","Return KeychainKind as a byte","","","","","","","","","","","","","","","","","","","","The confirmation time for transaction containing this utxo","The derivation index for the script pubkey in the wallet","Descriptors","Macro to write full descriptors with code","","","","","","","","","","","Macro to write descriptor fragments with code","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).","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 Psbt structure.","The weight of the witness data and scriptSig expressed in …","Get the sequence number if an explicit sequence number has …","","","","","","","","","","","","","","","","","Get the TxOut of the UTXO","Transaction output","","","","","The UTXO","Get the version of BDK at runtime","","","","","Wallet","The location of the output.","The information about the input we require to add it to a …","The nSequence value to set for this input.","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.","Alias for a Descriptor that can contain extended keys …","Trait implemented on Descriptors to add a method to …","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 …","Legacy ScriptContext To be used as P2SH scripts For …","The top-level miniscript abstract syntax tree (AST).","Multiple extended public keys.","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","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) …","Attempt to produce a non-malleable witness template given …","Attempt to produce a malleable witness template given the …","","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 …","Each context has slightly different rules on what Pks are …","","","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","Deprecated name for Self::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.","Add type information(Type and Extdata) to Miniscript based …","Create a new Miniscript from a Terminal node and a Type …","","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).","Extracts the AstElem representing the root of the …","Get as many descriptors as different paths in this …","Convert to wallet descriptor","","Whether or not the descriptor has any wildcards","Whether this descriptor contains a key that has multiple …","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 to conversion of a miniscript into a …","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 …","Computes an upper bound on the difference between a …","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 AST.","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 …","","","Returns a plan if the provided assets are sufficient to …","Returns a plan if the provided assets are sufficient to …","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","","","Substitutes raw public keys hashes with the public keys as …","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 miniscript can exceed the resource …","Compute the checksum of a descriptor, excludes any …","Compute the checksum bytes of a descriptor, excludes any …","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","The descriptor contains multipath keys","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}/*)","BIP86 template. Expands to tr(key/86'/{0,1}'/0'/{0,1}/*)","BIP86 public template. Expands to tr(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)","P2TR template. Expands to a descriptor tr(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.","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).","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","Multiple extended private keys.","Multiple extended public keys.","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 …","","","","","","","","","","","","","","","","","","","","","","","","","Attempt to produce a witness template given the assets …","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 …","Each context has slightly different rules on what Pks are …","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 for Self::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","Returns a vector containing the full derivation paths from …","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","Get as many keys as derivation paths in this key.","Get as many keys as derivation paths in this key.","Transform the ExtendedKey into an Xpriv for the given …","Transform the ExtendedKey into an Xpub for the given …","Whether or not the key has a wildcard","Returns whether the script context is Legacy","Returns whether the script context is …","Whether or not this key has multiple derivation paths.","Whether or not this key has multiple derivation paths.","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’…","A derived address and the index it was found at. For …","An error that may occur when applying a block to Wallet.","Balance, differentiated into various categories.","Occurs when the update chain cannot connect with original …","The changes made to a wallet by applying an Update.","The error variant that occurs when the caller attempts to …","There was problem with the passed-in descriptor(s).","There was a problem with the passed-in descriptor(s).","There is a problem with the passed-in descriptor.","An error that may occur when inserting a transaction into …","Trait to check if a value is below the dust limit. We are …","The error type when loading a Wallet from persistence.","The loaded desccriptor does not match what was provided.","The loaded genesis hash does not match what was provided.","The loaded network type does not match what was provided.","Data loaded from persistence is missing descriptor.","Data loaded from persistence is missing genesis hash.","Data loaded from persistence is missing network type.","The error type when constructing a fresh Wallet.","Error type for when we try load a Wallet from persistence …","Database already has data.","Wallet not initialized, persistence backend is empty.","Wallet is not initialized, persistence backend is empty.","We were unable to write the wallet’s data to the …","Loading data from the persistence backend failed.","Either writing to or loading from the persistence backend …","Occurs when the connected_to hash does not match the hash …","An update to Wallet.","A Bitcoin wallet","","Add an external signer","Address","Get unbounded script pubkey iterators for both Internal …","","Introduces a block of height to the wallet, and tries to …","Applies relevant transactions from block of height to the …","Apply relevant unconfirmed transactions to the wallet.","Applies an update to the wallet and stages the changes …","","","","","","","","","","","","","","","","","","","","","","Bump the fee of a transaction previously created with this …","Start building a transaction.","Calculates the fee of a given transaction. Returns 0 if tx …","Calculate the FeeRate for a given transaction.","Informs the wallet that you no longer intend to broadcast …","Update for the wallet’s internal LocalChain.","Changes to the LocalChain.","Get all the checkpoints the wallet is currently storing …","","","","","","","Coin selection","Commits all currently 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 …","","","","","","Errors that can be thrown by the Wallet","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.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Return the balance, separated into available, …","Returns the descriptor used to create addresses for a …","get the corresponding PSBT Input for a LocalUtxo","Get the signers","Get a single transaction from the wallet as a CanonicalTx …","Returns the utxo owned by this wallet corresponding to …","Update for the wallet’s internal TxGraph.","All coinbase outputs not yet matured","Child index of this address","Changes to IndexedTxGraph.","Add a new checkpoint to the wallet’s internal view of …","Add a transaction to the wallet’s internal view of the …","Inserts a TxOut at OutPoint into the wallet’s …","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).","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","Contains the last active derivation indices per keychain (K…","Returns the latest checkpoint.","List all relevant outputs (includes both spent and …","Return the list of unspent outputs of this wallet","List addresses that are revealed but unused.","Load Wallet from the given persistence backend.","Get a reference to the inner LocalChain.","Marks an address used of the given keychain at index.","Get the Bitcoin network the wallet is using.","Stores the network type of the wallet.","Initialize an empty Wallet.","Creates a wallet that does not persist data.","Creates a wallet that does not persist data, with a custom …","Either loads Wallet from persistence, or initializes it if …","Either loads Wallet from persistence, or initializes it if …","Initialize an empty Wallet with a custom genesis hash.","The index of the next address that you would get if you …","Get the next unused address for the given keychain, i.e. …","Peek an address of the given keychain at index without …","Return the spending policies for the wallet’s descriptor","","","","","","Return the “public” version of the wallet’s …","Reveal addresses up to and including the target index and …","Attempt to reveal the next address of the given keychain.","Return the secp256k1 context used for all signing …","Compute the tx’s sent and received Amounts.","","","Sign a transaction with all the wallet’s signers, in the …","Generalized signers","Get a reference to the inner KeychainTxOutIndex.","Returns the changes that will be committed with the next …","Create a `FullScanRequest for this wallet.","Create a partial SyncRequest for this wallet for all …","","","","","","","","","","","Get the whole balance visible to the wallet.","Iterate over the transactions in the wallet.","Unconfirmed UTXOs generated by a wallet tx","Get sum of trusted_pending and confirmed coins.","","","","","","","","","","","","","","","","","","","","","Transaction builder","Get a reference to the inner TxGraph.","","","","","","","","","","","Get an unbounded script pubkey iterator for the given …","Undoes the effect of mark_used and returns whether the …","Unconfirmed UTXOs received from an external wallet","","","","","","","","","","","Deterministically generate a unique name given the …","Block hash of connected_to.","Expected block hash of connected_to, as derived from block.","The internal chain’s tip height.","The introduced transaction’s confirmation height.","The expected genesis block hash.","The expected network type.","The block hash loaded from persistence.","The network type loaded from persistence.","The descriptor loaded from persistence.","The keychain of the descriptor not matching","Branch and bound coin selection tries to avoid needing a …","Branch and bound coin selection possible attempts with …","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 …","Errors that can be thrown by the coin_selection module","Remaining amount after performing coin selection","Wallet’s UTXO set is not enough to cover recipient’s …","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.","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).","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.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Sats available for spending","Sats needed for some transaction","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 …","Error returned from Wallet::build_fee_bump","The change_policy was set but the wallet does not have a …","There was an error with coin selection","Descriptor key conversion error","Error returned from TxBuilder::finish","There was a problem with the descriptors passed in","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 …","Wallet’s UTXO set is not enough to cover recipient’s …","Trying to replace a tx that has a sequence >= 0xFFFFFFFE","Requested LockTime is less than is required to spend from …","Miniscript PSBT error","Errors returned by miniscript when updating inconsistent …","In order to use the TxBuilder::add_global_xpubs option …","Missing non_witness_utxo on foreign utxo for given OutPoint","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","Return error type for …","We were unable to load wallet data from or write wallet …","There was a problem while extracting and manipulating …","Partially signed bitcoin transaction error","Cannot enable RBF with a Sequence >= 0xFFFFFFFE","Cannot enable RBF with Sequence given a required OP_CSV","Spending policy is not compatible with this KeychainKind","Happens when trying to bump a transaction that is already …","Thrown when a tx is not found in the internal database","Happens when trying to spend an UTXO that is not in the …","Happens when trying to spend an UTXO that is not in the …","Return error type for PsbtExt::update_input_with_descriptor","Requested invalid transaction version ‘0’","Requested transaction version 1, but at least 2 is needed …","","","","","","","","","","","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","","","","","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","","Sats available for spending","Required OP_CSV Sequence","Sats needed for some transaction","Given RBF Sequence","Requested LockTime","Required LockTime","Required fee absolute value (satoshi)","Required fee rate","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.","To be used only by external libraries implementing …","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","Miniscript PSBT error","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 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 …","Whether to remove taproot specific fields from the PSBT on …","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","Error returned from TxBuilder::add_foreign_utxo.","Error returned from TxBuilder::add_utxo and …","Error returned from TxBuilder::allow_shrinking","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 …","Requested outpoint doesn’t exist in the tx (vout greater …","Foreign utxo outpoint txid does not match PSBT input txid","Script/PubKey was not in the original transaction","Foreign utxo missing witness_utxo or non_witness_utxo","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","Happens when trying to spend an UTXO that is not in the …","Unchanged","Add data as an output, using OP_RETURN","Add a foreign UTXO i.e. a UTXO not owned by this wallet.","Same as add_foreign_utxo but allows to set the nSequence …","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 The fee_absolute method refers to the …","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.","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).","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","","","","","","","","","Foreign UTXO outpoint","PSBT input txid"],"i":[1,5,0,1,0,5,0,0,0,0,0,0,1,1,1,3,4,5,1,3,4,5,0,1,3,4,5,1,3,4,5,1,3,3,0,0,1,3,1,3,4,5,1,3,4,5,0,1,3,4,5,1,3,1,3,4,5,3,3,0,5,3,1,0,4,5,1,3,0,0,1,3,4,5,1,3,4,5,1,3,4,5,5,3,1,3,4,5,4,0,1,3,4,5,0,209,209,209,17,0,0,0,0,0,0,0,0,49,0,0,26,17,0,0,0,17,26,0,17,17,17,26,17,35,36,23,23,17,17,35,36,23,17,35,36,23,23,23,23,0,49,35,36,49,36,49,49,35,36,49,35,36,49,49,35,36,49,35,36,49,35,36,0,17,35,36,23,17,35,36,23,17,35,36,23,23,17,17,17,17,17,17,23,17,23,17,35,36,23,0,17,23,23,210,17,23,17,17,17,35,36,23,23,17,23,17,17,17,17,17,17,17,35,36,23,23,23,17,23,23,23,17,23,23,23,17,17,23,23,17,17,35,36,23,17,35,36,23,23,17,175,63,17,17,23,23,23,17,23,23,49,35,36,23,17,23,17,49,35,36,17,17,17,17,17,17,17,17,17,17,17,17,17,17,23,49,23,17,23,23,17,35,36,23,49,35,36,17,17,0,23,17,23,17,23,23,17,17,23,17,23,49,35,36,23,0,17,35,36,23,17,23,17,49,49,17,23,17,35,36,23,17,35,36,23,23,17,35,36,23,17,17,35,36,23,23,0,0,48,48,0,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,84,76,76,0,85,0,0,84,83,0,84,84,76,76,76,84,85,46,76,85,85,0,0,0,46,46,83,84,84,0,0,84,84,84,83,83,84,85,47,86,76,46,83,84,85,47,86,76,46,83,84,85,47,86,46,83,84,85,47,86,46,47,86,86,83,84,85,47,86,76,83,84,85,47,86,76,76,46,83,84,85,85,47,47,86,76,46,47,83,86,84,47,83,84,85,47,86,76,46,84,85,86,47,86,76,47,47,83,84,85,47,86,86,83,84,85,47,86,46,76,83,84,85,47,86,76,46,83,84,85,47,86,76,46,83,84,85,47,86,76,46,83,84,85,47,86,76,46,211,211,211,212,213,214,213,214,213,214,213,214,213,214,215,216,217,218,219,220,220,219,221,222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,223,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,87,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,81,0,0,0,0,224,224,0,0,111,0,0,0,0,81,81,81,49,0,0,22,81,81,108,26,224,115,0,115,0,0,22,26,108,0,0,0,0,22,0,111,108,26,0,225,26,115,106,113,22,107,81,104,26,108,109,110,111,115,106,113,22,107,81,104,26,108,109,110,111,104,49,49,49,49,49,49,49,49,49,106,22,107,104,26,108,109,110,111,106,22,107,104,26,108,109,110,111,104,26,109,111,107,107,106,26,26,104,22,104,26,108,109,110,111,113,22,107,81,81,104,104,26,26,108,108,109,110,111,104,115,115,115,106,113,22,107,81,81,81,104,26,26,108,109,110,111,113,113,26,108,104,26,26,224,226,224,226,115,26,104,26,109,111,115,106,113,22,107,81,104,26,108,109,110,111,26,88,94,106,106,113,26,108,94,115,106,106,26,108,115,115,26,225,22,26,108,225,22,225,22,26,26,104,109,110,104,0,26,49,104,104,0,49,104,26,109,110,49,113,104,26,109,111,49,104,81,104,104,104,26,49,104,0,106,22,107,104,26,108,109,110,111,108,81,104,26,108,49,49,104,115,106,113,22,107,81,104,26,108,109,110,111,115,106,113,22,107,81,104,26,108,109,110,111,115,106,113,22,107,81,104,26,108,109,110,111,115,106,113,22,107,81,104,26,108,109,110,111,0,227,227,227,0,0,0,156,0,155,152,153,154,0,0,0,154,154,154,153,153,153,0,0,152,153,154,152,153,154,156,0,0,123,124,148,124,129,124,124,124,124,124,123,124,135,129,148,152,153,154,155,156,123,124,135,129,148,152,153,154,155,156,124,124,124,124,124,135,129,124,123,135,129,123,135,129,0,124,123,123,135,129,148,124,124,124,123,129,123,129,148,0,0,124,123,123,124,135,129,148,148,152,152,153,153,154,154,155,155,156,156,123,124,135,135,135,129,129,129,148,152,153,154,155,156,124,124,124,124,124,124,135,123,148,129,124,124,124,123,124,135,129,148,152,153,154,155,156,228,129,124,148,124,135,124,124,124,124,124,124,124,124,129,124,124,124,124,124,124,124,124,124,124,152,153,154,155,156,124,124,124,124,124,123,129,124,0,124,124,124,124,123,135,129,123,148,152,153,154,155,156,123,124,123,123,123,124,135,129,148,152,153,154,155,156,123,124,135,129,148,152,153,154,155,156,0,124,123,124,135,129,148,152,153,154,155,156,124,124,123,123,124,135,129,148,152,153,154,155,156,0,229,229,230,230,231,232,231,232,233,233,185,185,0,186,0,0,0,0,0,185,0,186,0,185,186,184,181,182,183,185,186,184,181,182,183,181,182,183,181,182,183,201,181,182,183,0,181,182,183,184,184,185,185,186,184,181,182,183,185,186,184,181,182,183,185,186,184,181,182,183,184,183,185,184,184,181,182,183,185,185,186,184,181,182,183,185,186,184,181,182,183,185,186,184,181,182,183,185,186,184,181,182,183,234,234,235,236,236,235,236,0,165,165,187,0,165,165,142,165,165,142,165,165,0,165,165,165,165,165,187,165,165,165,165,165,165,142,142,165,142,187,165,165,187,165,142,187,165,142,187,187,187,187,165,165,142,142,187,165,165,165,165,165,165,142,187,165,142,187,165,142,187,187,165,142,187,165,142,187,165,142,187,165,142,187,165,142,237,238,237,238,239,239,240,241,0,0,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,195,190,195,151,190,195,151,0,151,151,151,192,151,151,151,151,151,151,151,195,190,192,151,0,0,0,0,0,0,0,0,192,0,0,151,45,150,150,45,150,190,151,192,194,125,45,150,195,190,151,192,194,125,45,150,195,45,190,192,194,125,45,150,195,190,192,194,125,45,150,195,190,125,125,45,150,195,194,242,194,194,194,190,192,125,195,45,190,151,151,192,194,125,45,150,195,190,190,190,151,151,192,194,125,45,150,195,190,242,194,194,194,45,190,151,192,194,125,45,150,195,194,45,190,125,151,45,150,150,243,194,194,194,126,194,150,45,150,190,192,194,125,45,150,195,151,150,150,190,151,192,194,125,45,150,195,190,151,192,194,125,45,150,195,190,151,192,194,125,45,150,195,190,151,192,194,125,45,150,195,244,0,0,0,206,0,205,205,0,0,202,202,204,202,205,206,0,0,0,203,206,141,141,141,141,141,141,141,141,141,141,143,140,141,203,202,204,206,205,143,140,141,203,202,204,206,205,141,143,140,141,206,205,143,140,141,206,205,206,205,141,141,143,140,206,205,141,141,141,141,141,206,205,141,141,141,143,140,141,203,203,202,202,204,204,206,205,143,140,141,203,202,204,206,205,206,205,141,143,140,141,203,202,204,206,205,141,141,141,141,141,206,205,141,203,202,204,141,141,206,143,140,141,206,205,203,202,204,143,140,141,203,202,204,206,205,143,140,141,203,202,204,206,205,143,140,141,203,202,204,206,205,141,141,143,140,141,203,202,204,206,205,245,245],"f":[0,0,0,0,0,0,0,0,0,0,0,0,[1,2],[1],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[1,1],[3,3],[4,4],[5,5],[[]],[[]],[[]],[[]],[[1,1],6],0,0,0,0,[[],[[7,[1]]]],[[],[[7,[3]]]],[[1,1],8],[[3,3],8],[[4,4],8],[[5,5],8],[[1,9],10],[[3,9],10],[[4,9],10],[[5,9],10],0,[[]],[[]],[[]],[[]],[1],[3],[[]],[[]],[[]],[[]],0,0,0,[5,11],0,[[1,1],[[12,[6]]]],0,0,[5,[[12,[13]]]],[1,7],[3,7],0,0,[[]],[[]],[[]],[[]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[5,14],0,[[],15],[[],15],[[],15],[[],15],0,[[],16],[[]],[[]],[[]],[[]],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,[[17,18],[[7,[[20,[19]],21]]]],[[],22],[[],22],[23,24],[23,[[25,[23]]]],[[[17,[26]],27],[[7,[[17,[28]],29]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[23,[[31,[23,30]]]],[23,[[33,[32]]]],[23,[[33,[32]]]],0,[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[24,[[7,[34]]]],[24,[[7,[34]]]],[24,[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],0,[17,17],[35,35],[36,36],[23,23],[[]],[[]],[[]],[[]],[[17,17],6],[[35,35],6],[[36,36],6],[[23,23],6],[23,8],[[[17,[26]],27],[[7,[[17,[28]],29]]]],[[[17,[28]],37],[[7,[[17,[38]],29]]]],[[[17,[26]],37,27],[[7,[[17,[38]],29]]]],[17,39],[[[17,[26]]],40],[[],[[7,[17]]]],[[],[[7,[23]]]],[[[17,[26]]],41],[23,42],[[17,17],8],[[35,35],8],[[36,36],8],[[23,23],8],0,[17,[[7,[42,21]]]],0,[[23,43],[[7,[44]]]],[[45,46,37],[[7,[[12,[47]],48]]]],[[[17,[26]],45,46,37],[[7,[[12,[47]],48]]]],[[[23,[26,49]],45,46,37],[[7,[[12,[47]],48]]]],[[[17,[26]],37,50,[51,[27]]],[[7,[12,29]]]],[[17,9],[[7,[52]]]],[[17,9],[[7,[52]]]],[[35,9],[[7,[52]]]],[[36,9],[[7,[52]]]],[[23,9],[[7,[52]]]],[[23,9],[[7,[52]]]],[17,8],[23,8],[[]],[53,17],[54,17],[55,17],[56,17],[57,17],[58,17],[[]],[[]],[[]],[24,[[7,[23,21]]]],[[24,59,60],23],[16,[[7,[17,21]]]],[16,[[7,[23,21]]]],[[16,43],[[7,[23,21]]]],[16,[[7,[23,21]]]],[61,[[7,[17,21]]]],[61,[[7,[23,21]]]],[[23,62],[[12,[23]]]],[[23,62],12],[17,[[7,[21]]]],[17,[[7,[21]]]],[23,8],[23,8],[[[17,[26]]],8],[17],[35],[36],[23],[[]],[[]],[[]],[[]],[23,24],[[[17,[26]]],[[7,[[31,[[17,[26]],30]],21]]]],[[37,18],[[7,[48]]]],[[63,37,18],[[7,[48]]]],[[[17,[26]]],8],[[[17,[26]]],8],[23,8],[23,64],[23,65],[17,[[7,[66,21]]]],[23,[[7,[66,21]]]],[23,[[7,[67]]]],[23,[[12,[62]]]],[23,[[12,[62]]]],[23,[[12,[62]]]],[23,[[7,[62,21]]]],[17,[[7,[62,21]]]],[23,[[7,[62,21]]]],[17,[[7,[62,21]]]],[[],16],[[],16],[[],16],[[[23,[68]]],[[7,[17,21]]]],[[],17],[[],[[7,[17,21]]]],[[[23,[35]]],[[7,[17,21]]]],[[62,[31,[30]]],[[7,[17,21]]]],[53,17],[54,17],[[],[[7,[17,21]]]],[[[23,[36]]],[[7,[17,21]]]],[[62,[31,[30]]],[[7,[17,21]]]],[[[12,[69]]],[[7,[17,21]]]],[[],[[7,[17,21]]]],[[[23,[36]]],[[7,[17,21]]]],[[62,[31,[30]]],[[7,[17,21]]]],0,[23,[[7,[21]]]],[50,[[7,[23,21]]]],[[37,16],[[7,[21]]]],[50,[[7,[23,21]]]],[[50,43],[[7,[23,21]]]],[[17,17],[[12,[6]]]],[[35,35],[[12,[6]]]],[[36,36],[[12,[6]]]],[[23,23],[[12,[6]]]],[[],62],[[],62],[[],62],[[[17,[28]]],[[7,[70,[17,[28]]]]]],[[[17,[28]]],[[7,[70,[17,[28]]]]]],0,[23,8],[17,[[7,[21]]]],[23,[[7,[44]]]],[[17,71],[[7,[21]]]],[23,[[7,[[31,[[31,[2,30]],30]],21]]]],[23,[[7,[[31,[[31,[2,30]],30]],21]]]],[17,[[7,[42,21]]]],[17,42],[23,62],[17,7],[23,7],[[],72],[[],72],[[],72],[[23,73],23],0,[[]],[[]],[[]],[[]],[[],74],[[],74],[[[17,[26]],73],74],[23,[[7,[21]]]],[23,[[7,[21]]]],[17,[[7,[75]]]],[23,[[7,[75]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],0,[[],15],[[],15],[[],15],[[],15],[17,42],[[]],[[]],[[]],[[]],[23,8],[16,[[7,[74,48]]]],[16,[[7,[48]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[48,9],10],[[48,9],10],[21,48],[76,48],[[]],[77,48],[78,48],[79,48],[80,48],[81,48],[[]],[82],[[],74],[[],7],[[],7],[[],15],[[]],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,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[83,83],[84,84],[85,85],[47,47],[86,86],[46,46],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[],86],[[83,83],8],[[84,84],8],[[85,85],8],[[47,47],8],[[86,86],8],[[76,76],8],[[83,9],10],[[84,9],10],[[85,9],10],[[47,9],10],[[86,9],10],[[76,9],10],[[76,9],10],[[46,9],10],[[]],[[]],[[]],[8,85],[84,47],[[]],[[]],[[]],[[]],[[47,73],[[7,[86,76]]]],[83],[86],[84,74],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[84,8],[85,8],[86,8],0,[[86,86],[[12,[6]]]],[82],[47,8],0,[83,7],[84,7],[85,7],[47,7],[86,7],0,[[]],[[]],[[]],[[]],[[]],[[]],[[],74],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],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,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[18,[[7,[87,48]]]],[[[89,[[88,[35]]]],18],[[7,[87,48]]]],[[[90,[[88,[36]]]],18],[[7,[87,48]]]],[[[91,[[88,[36]]]],18],[[7,[87,48]]]],[[[93,[[88,[92]]]],18],[[7,[87,48]]]],[[[95,[[94,[35]]]],18],[[7,[87,48]]]],[[[96,[[94,[35]]]],18],[[7,[87,48]]]],[[[97,[[94,[36]]]],18],[[7,[87,48]]]],[[[98,[[94,[36]]]],18],[[7,[87,48]]]],[[[99,[[94,[36]]]],18],[[7,[87,48]]]],[[[100,[[94,[36]]]],18],[[7,[87,48]]]],[[[101,[[94,[92]]]],18],[[7,[87,48]]]],[[[102,[[94,[92]]]],18],[[7,[87,48]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[87,37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],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,[[],103],[[],22],[[26,27],[[7,[28,29]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[104,[[33,[32]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[[],[[7,[34]]]],[24,[[7,[34]]]],[[],[[7,[34]]]],[[[106,[105,49]]],[[106,[105,49]]]],[22,22],[107,107],[104,104],[26,26],[108,108],[109,109],[110,110],[111,111],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[104,104],6],[[26,26],6],[[109,109],6],[[111,111],6],0,[[],107],[[[106,[49]]]],[[26,27],[[7,[28,29]]]],[[],[[7,[26]]]],[104,42],[[22,22],8],[[104,104],8],[[26,26],8],[[108,108],8],[[109,109],8],[[110,110],8],[[111,111],8],[[[113,[[0,[112,49]]]],9],10],[[22,9],10],[[107,9],10],[[81,9],10],[[81,9],10],[[104,9],[[7,[52]]]],[[104,9],[[7,[52]]]],[[26,9],[[7,[52]]]],[[26,9],[[7,[52]]]],[[108,9],[[7,[52]]]],[[108,9],[[7,[52]]]],[[109,9],[[7,[52]]]],[[110,9],[[7,[52]]]],[[111,9],[[7,[52]]]],[104,8],[[]],[114,[[115,[49]]]],[116,[[115,[49]]]],[[]],[[]],[[]],[[]],[80,81],[[]],[21,81],[[]],[28,26],[[]],[[]],[[]],[[]],[[]],[[26,103],[[113,[49]]]],[[108,103],[[113,[49]]]],[16,[[7,[26]]]],[16,[[7,[108]]]],[61,[[7,[104,21]]]],[26,[[12,[117]]]],[26,[[31,[117,30]]]],[[],[[7,[106]]]],[[],[[7,[106]]]],[[],[[7,[106]]]],[[],[[7,[106]]]],[[[115,[49]]],8],[26,8],[104],[26],[109],[111],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[26,118],[[],[[7,[113,81]]]],[[[12,[119]],117],[[7,[113,81]]]],[106,[[7,[113,81]]]],[[106,[12,[119]],117],[[7,[113,81]]]],[[[113,[49]]],[[7,[[113,[49]],81]]]],[26,[[7,[[113,[49]],81]]]],[108,[[7,[[113,[49]],81]]]],[[],[[7,[115,81]]]],[[[115,[49]]],[[7,[[115,[49]],81]]]],[106,[[7,[115,81]]]],[[[106,[49]]]],[26,[[31,[26,30]]]],[108,[[31,[108,30]]]],[[[115,[49]],18],[[12,[116]]]],[[[115,[49]],18,37],114],[26,8],[[],8],[22,8],[26,8],[108,8],[[],8],[22,8],[[],8],[22,8],[26,8],[26,8],0,0,0,[104,[[7,[66,21]]]],[[],103],[26,120],[23,[[12,[62]]]],[104,62],[104,62],[[103,103],103],[[],16],[[62,[31,[30]]],[[7,[104,21]]]],[26,62],0,0,[23,[[7,[21]]]],[[[113,[49]],103],[[113,[49]]]],[[104,104],[[12,[6]]]],[[26,26],[[12,[6]]]],[[109,109],[[12,[6]]]],[[111,111],[[12,[6]]]],[[],62],0,[82],[104,[[7,[21]]]],[104,[[7,[[31,[[31,[2,30]],30]],21]]]],[104,62],[26,7],[[],72],[104,24],[[],103],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[108,37],[[7,[26,121]]]],[[],74],[[],74],[[],74],[[],74],[23,[[7,[21]]]],[23,[[7,[21]]]],[104,[[7,[104,75]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],[[12,[41]]]],[[],[[12,[122]]]],[62,[[12,[14]]]],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,[[123,123],123],[[124,1,125,[127,[126]]]],0,[124,[[73,[1,[0,[128,105]]]]]],[[129,129]],[[124,130,27],[[7,[131]]]],[[124,130,27,132],[[7,[133]]]],[[124,134]],[[124,[136,[135]]],[[7,[131]]]],[124,137],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[124,138],[[7,[[141,[139,140]],142]]]],[124,[[141,[139,143]]]],[[124,144],[[7,[41,145]]]],[[124,144],[[7,[122,145]]]],[[124,144]],0,0,[124,146],[123,123],[135,135],[129,129],[[]],[[]],[[]],0,[124,[[147,[8]]]],0,[[],123],[[],135],[[],129],[148],[[124,1],[[12,[27]]]],[[124,50],12],[[124,1],74],[[],[[7,[123]]]],[[],[[7,[129]]]],[[123,123],8],[[129,129],8],[[148,148],8],0,0,[[124,149,150],[[7,[8,151]]]],[[123,9],[[7,[52]]]],[[123,9],[[7,[52]]]],[[124,9],10],[[135,9],10],[[129,9],10],[[148,9],10],[[148,9],10],[[152,9],10],[[152,9],10],[[153,9],10],[[153,9],10],[[154,9],10],[[154,9],10],[[155,9],10],[[155,9],10],[[156,9],10],[[156,9],10],[[]],[[]],[157,135],[[]],[[[158,[1]]],135],[[[161,[159,[160,[1]]]]],129],[[]],[162,129],[[]],[[]],[[]],[[]],[[]],[[]],[124,123],[[124,1],63],[[124,3,[12,[163]],8],[[7,[164,165]]]],[[124,1],[[127,[45]]]],[[124,138],[[12,[[166,[[127,[144]],159]]]]]],[[124,11],[[12,[3]]]],0,0,0,0,[[124,132],[[7,[8,167]]]],[[124,144,168],[[7,[8,155]]]],[[124,11,14]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[50,8],[129,8],[[124,50],8],0,[124,128],0,[124,169],[124,128],[124,128],[[124,1],170],[[[0,[[171,[129]],172,173]]],[[7,[124,153]]]],[124,174],[[124,1,27],8],[124,18],0,[[175,[12,[175]],[0,[[171,[129]],172,173]],18],[[7,[124,152]]]],[[175,[12,[175]],18],[[7,[124,48]]]],[[175,[12,[175]],18,176],[[7,[124,48]]]],[[175,[12,[175]],[0,[[171,[129]],172,173]],18],[[7,[124,154]]]],[[175,[12,[175]],[0,[[171,[129]],172,173]],18,176],[[7,[124,154]]]],[[175,[12,[175]],[0,[[171,[129]],172,173]],18,176],[[7,[124,152]]]],[[124,1],27],[[124,1],[[147,[148]]]],[[124,1,27],148],[[124,1],[[7,[[12,[47]],48]]]],[82],[82],[82],[82],[82],[[124,1],[[12,[63]]]],[[124,1,27],[[147,[128]]]],[[124,1],[[147,[148]]]],[124,37],[[124,144]],[123,7],[129,7],[[124,149,150],[[7,[8,151]]]],0,[124,177],[124,129],[124,[[178,[1]]]],[124,179],[[]],[[]],[[]],[[],74],[[],74],[[],74],[[],74],[[],74],[[],74],[[],74],[123,180],[124,128],0,[123,180],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],0,[124,137],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[124,1],[[0,[128,105]]]],[[124,1,27],8],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[12,18,37],[[7,[74,48]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[181,181],[182,182],[183,183],[[]],[[]],[[]],[[[31,[4]],[31,[4]],122,41,50],[[7,[184,185]]]],[[181,[31,[4]],[31,[4]],122,41,50],[[7,[184,185]]]],[[182,[31,[4]],[31,[4]],122,41,50],[[7,[184,185]]]],[[183,[31,[4]],[31,[4]],122,41,50],[[7,[184,185]]]],[[41,122,50],186],[[],181],[[],182],[[],183],0,0,[[185,9],10],[[185,9],10],[[186,9],10],[[184,9],10],[[181,9],10],[[182,9],10],[[183,9],10],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[184,41],[41,183],[82],0,[184,41],[[]],[[]],[[]],[[],74],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],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,[[]],[[]],[[]],[[]],[[]],[[]],[187,187],[[]],[[187,9],10],[[187,9],10],[[165,9],10],[[165,9],10],[[142,9],10],[[142,9],10],[[]],[185,165],[[]],[188,165],[48,165],[76,165],[187,165],[[]],[[]],[[]],[[]],[82],[82],[82],[[]],[[],74],[[],74],[[],74],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[189,[[12,[74]]]],[189,74],[[],[[7,[189]]]],[[124,16,8],[[7,[189,16]]]],[[189,9],10],[[189,9],10],[[]],[16,[[7,[189]]]],[[]],0,[189,7],[[],74],[[],7],[[],7],[[],15],[[]],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,[[45,190,125,[127,[126]]],[[12,[[127,[126]]]]]],0,0,[[45,37],191],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[191,17,37],45],[190,190],[192,192],[[[194,[[0,[105,193,112,105]]]]],[[194,[[0,[105,193,112,105]]]]]],[125,125],[45,45],[150,150],[195,195],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[190,190],6],[[125,125],6],[[],125],[[],45],[[],150],[[],195],[[[194,[[0,[193,112,105]]]]]],[[],[[12,[108]]]],[[[194,[[196,[116]]]]],[[12,[108]]]],[[[194,[197]]],[[12,[108]]]],[[[194,[[198,[116]]]]],[[12,[108]]]],[[190,190],8],[[192,192],8],[[125,125],8],[[195,195],8],[[45,190],[[12,[127]]]],[[190,9],10],[[151,9],10],[[151,9],10],[[192,9],10],[[[194,[[0,[112,193,112,105]]]],9],10],[[125,9],10],[[45,9],10],[[150,9],10],[[195,9],10],[199,190],[120,190],[[]],[[]],[200,151],[[]],[[]],[[]],[[]],[[]],[[]],[190],[37,190],[[[194,[197]],37],190],[[[194,[[198,[116]]]],37],190],[[[194,[[196,[116]]]],37],190],[45,[[31,[190]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[0,[193,112,105]],192],[[194,[[0,[193,112,105]]]]]],[[],45],[[190,190],[[12,[6]]]],[[125,125],[[12,[6]]]],[82],[[45,190,125],[[12,[[127,[126]]]]]],0,0,[[149,62,150,37],[[7,[151]]]],[[[194,[[198,[116]]]],149,62,150,37],[[7,[151]]]],[[[194,[197]],149,62,150,37],[[7,[151]]]],[[[194,[[196,[116]]]],149,62,150,37],[[7,[151]]]],[[149,150,37],[[7,[151]]]],[[149,150,37],[[7,[151]]]],0,[45,[[31,[127]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],74],0,0,[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[[141,[201,143]]],[[141,[201,143]]]],[[141,11,164,62],[[7,[141,202]]]],[[141,11,164,62,13],[[7,[141,202]]]],[141,141],[[[141,[201,143]],42,180],[[141,[201,143]]]],[[141,11],141],[[141,11],[[7,[141,203]]]],[141,[[7,[141,203]]]],[[141,8],141],[[[141,[139,140]],42],[[7,[[141,[139,140]],204]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[141,205],141],[143,143],[140,140],[[[141,[105]]],[[141,[105]]]],[206,206],[205,205],[[]],[[]],[[]],[[]],[[]],[[206,206],6],[[205,205],6],[[141,201],[[141,[201]]]],[[141,27],141],[[],143],[[],140],[[],206],[[],205],[141,141],[[[141,[201,143]],42],[[141,[201,143]]]],[141,141],[141,141],[[141,13],141],[[206,206],8],[[205,205],8],[[141,41],141],[[141,122],141],[[[141,[201]]],[[7,[149,165]]]],[[143,9],10],[[140,9],10],[[[141,[112,112]],9],10],[[203,9],10],[[203,9],10],[[202,9],10],[[202,9],10],[[204,9],10],[[204,9],10],[[206,9],10],[[205,9],10],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[206],[205],[141,141],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[141,141],[[141,207],141],[141,141],[141,141],[[141,206],141],[[206,206],[[12,[6]]]],[[205,205],[[12,[6]]]],[[141,[73,[74,[31,[62]]]],1],141],[82],[82],[82],[[[141,[201,143]],31],[[141,[201,143]]]],[[141,163],141],[[206,144]],[[]],[[]],[[]],[[]],[[]],[[],74],[[],74],[[],74],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[141,[31,[11]]],141],[[141,208],141],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0],"p":[[4,"KeychainKind"],[15,"u8"],[3,"LocalOutput"],[3,"WeightedUtxo"],[4,"Utxo"],[4,"Ordering"],[4,"Result"],[15,"bool"],[3,"Formatter"],[6,"Result"],[3,"OutPoint"],[4,"Option"],[3,"Sequence"],[3,"TxOut"],[3,"TypeId"],[15,"str"],[4,"Descriptor"],[4,"Network"],[4,"NetworkChecked"],[3,"Address"],[4,"Error"],[4,"ScriptContextEnum"],[3,"Miniscript"],[4,"Terminal"],[4,"Tree"],[4,"DescriptorPublicKey"],[15,"u32"],[3,"DefiniteDescriptorKey"],[4,"ConversionError"],[3,"Global"],[3,"Vec"],[4,"Placeholder"],[3,"Satisfaction"],[4,"ScriptContextError"],[4,"Legacy"],[4,"Segwitv0"],[3,"Secp256k1"],[3,"PublicKey"],[4,"DescriptorType"],[3,"DescriptorId"],[15,"u64"],[3,"ScriptBuf"],[3,"ExtParams"],[4,"AnalysisError"],[3,"SignersContainer"],[4,"BuildSatisfaction"],[3,"Policy"],[4,"Error"],[8,"ScriptContext"],[3,"Script"],[3,"Range"],[3,"Error"],[3,"Wpkh"],[3,"Wsh"],[3,"Tr"],[3,"Bare"],[3,"Sh"],[3,"Pkh"],[3,"Type"],[3,"ExtData"],[3,"Tree"],[15,"usize"],[6,"ExtendedDescriptor"],[3,"Iter"],[3,"PkIter"],[4,"Policy"],[4,"LiftError"],[4,"BareCtx"],[4,"TapTree"],[3,"Plan"],[3,"TxIn"],[4,"SigType"],[3,"BTreeMap"],[3,"String"],[4,"TranslateErr"],[4,"PolicyError"],[4,"HexToBytesError"],[4,"Error"],[4,"Error"],[4,"Error"],[4,"KeyError"],[3,"Demand"],[4,"PkOrF"],[4,"SatisfiableItem"],[4,"Satisfaction"],[3,"Condition"],[6,"DescriptorTemplateOut"],[8,"IntoDescriptorKey"],[3,"P2Pkh"],[3,"P2Wpkh_P2Sh"],[3,"P2Wpkh"],[4,"Tap"],[3,"P2TR"],[8,"DerivableKey"],[3,"Bip44"],[3,"Bip44Public"],[3,"Bip49"],[3,"Bip49Public"],[3,"Bip84"],[3,"Bip84Public"],[3,"Bip86"],[3,"Bip86Public"],[6,"ValidNetworks"],[3,"SortedMultiVec"],[8,"Clone"],[3,"GeneratedKey"],[3,"PrivateKeyGenerateOptions"],[4,"DescriptorSecretKey"],[3,"SinglePub"],[3,"SinglePriv"],[4,"SinglePubKey"],[8,"Debug"],[4,"DescriptorKey"],[3,"Xpub"],[4,"ExtendedKey"],[3,"Xpriv"],[3,"DerivationPath"],[3,"Assets"],[6,"KeySource"],[3,"Fingerprint"],[3,"DescriptorKeyParseError"],[3,"FeeRate"],[3,"Balance"],[3,"Wallet"],[3,"SignerOrdering"],[8,"TransactionSigner"],[3,"Arc"],[8,"Iterator"],[3,"ChangeSet"],[3,"Block"],[3,"CannotConnectError"],[3,"BlockId"],[4,"ApplyHeaderError"],[8,"IntoIterator"],[3,"Update"],[8,"Into"],[3,"TxGraph"],[3,"Txid"],[6,"DefaultCoinSelectionAlgorithm"],[3,"BumpFee"],[3,"TxBuilder"],[4,"BuildFeeBumpError"],[3,"CreateTx"],[3,"Transaction"],[4,"CalculateFeeError"],[3,"CheckPointIter"],[6,"Result"],[3,"AddressInfo"],[3,"Psbt"],[3,"SignOptions"],[4,"SignerError"],[4,"NewError"],[4,"LoadError"],[4,"NewOrLoadError"],[4,"InsertTxError"],[4,"ApplyBlockError"],[3,"SyncResult"],[3,"FullScanResult"],[3,"ConfirmationTimeHeightAnchor"],[3,"ChangeSet"],[3,"ChangeSet"],[6,"ChangeSet"],[3,"PsbtSighashType"],[3,"Input"],[4,"CreateTxError"],[3,"CanonicalTx"],[3,"AlterCheckPointError"],[4,"ConfirmationTime"],[3,"CheckPoint"],[8,"DoubleEndedIterator"],[8,"PersistBackend"],[8,"Send"],[8,"Sync"],[3,"LocalChain"],[8,"IntoWalletDescriptor"],[3,"BlockHash"],[3,"KeychainTxOutIndex"],[3,"FullScanRequest"],[3,"SyncRequest"],[3,"Amount"],[3,"LargestFirstCoinSelection"],[3,"OldestFirstCoinSelection"],[3,"BranchAndBoundCoinSelection"],[3,"CoinSelectionResult"],[4,"Error"],[4,"Excess"],[4,"MiniscriptPsbtError"],[4,"Error"],[3,"FullyNodedExport"],[4,"SignerId"],[6,"KeyMap"],[4,"SignerContext"],[8,"Sized"],[3,"SignerWrapper"],[4,"TapLeavesOptions"],[3,"DescriptorMultiXKey"],[3,"PrivateKey"],[3,"DescriptorXKey"],[3,"Hash"],[4,"Error"],[8,"CoinSelectionAlgorithm"],[4,"AddForeignUtxoError"],[4,"AddUtxoError"],[4,"AllowShrinkingError"],[4,"ChangeSpendPolicy"],[4,"TxOrdering"],[4,"LockTime"],[15,"i32"],[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,"UnexpectedConnectedToHash"],[13,"ConfirmationHeightCannotBeGreaterThanTip"],[13,"LoadedGenesisDoesNotMatch"],[13,"LoadedNetworkDoesNotMatch"],[13,"LoadedDescriptorDoesNotMatch"],[13,"InsufficientFunds"],[13,"Change"],[13,"NoChange"],[13,"InsufficientFunds"],[13,"RbfSequenceCsv"],[13,"LockTime"],[13,"FeeTooLow"],[13,"FeeRateTooLow"],[8,"SignerCommon"],[8,"InputSigner"],[13,"Tap"],[13,"InvalidTxid"]]},\ "bdk_bitcoind_rpc":{"doc":"This crate is used for emitting blockchain data from the …","t":[8,3,3,2,12,11,11,11,11,11,11,12,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11],"n":["BitcoindRpcErrorExt","BlockEvent","Emitter","bitcoincore_rpc","block","block_hash","block_height","borrow","borrow","borrow_mut","borrow_mut","checkpoint","connected_to","fmt","from","from","into","into","is_not_found_error","mempool","new","next_block","next_header","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip"],"q":["bdk_bitcoind_rpc","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Extends bitcoincore_rpc::Error.","A newly emitted block from Emitter.","The Emitter is used to emit data sourced from …","","Either a full Block or Header of the new block.","The block hash of this new block.","The block height of this new block.","","","","","The checkpoint of the new block.","The BlockId of a previous block that this block connects …","","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Returns whether the error is a “not found” error.","Emit mempool transactions, alongside their first-seen unix …","Construct a new Emitter.","Emit the next block height and block (if any).","Emit the next block height and header (if any).","","","","","","","",""],"i":[0,0,0,0,1,1,1,10,1,10,1,1,1,1,10,1,10,1,19,10,10,10,10,10,1,10,1,10,1,10,1],"f":[0,0,0,0,0,[1,2],[1,3],[[]],[[]],[[]],[[]],0,[1,4],[[[1,[5]],6],7],[[]],[[]],[[]],[[]],[[],8],[[[10,[9]]],[[13,[11,12]]]],[[14,3],[[10,[9]]]],[[[10,[9]]],[[13,[[16,[[1,[15]]]],12]]]],[[[10,[9]]],[[13,[[16,[[1,[17]]]],12]]]],[[],13],[[],13],[[],13],[[],13],[[],18],[[],18],[[]],[[]]],"p":[[3,"BlockEvent"],[3,"BlockHash"],[15,"u32"],[3,"BlockId"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[15,"bool"],[8,"RpcApi"],[3,"Emitter"],[3,"Vec"],[4,"Error"],[4,"Result"],[3,"CheckPoint"],[3,"Block"],[4,"Option"],[3,"Header"],[3,"TypeId"],[8,"BitcoindRpcErrorExt"]]},\ "bdk_chain":{"doc":"This crate is a collection of core structures for Bitcoin …","t":[8,8,8,17,3,17,8,4,3,4,3,13,13,8,3,16,3,2,3,3,2,13,13,11,11,10,11,11,11,12,12,10,11,11,11,11,11,2,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,12,12,11,11,11,11,11,12,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,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,11,12,12,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,10,11,12,11,11,11,0,0,11,2,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,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,0,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,3,16,3,8,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,12,12,10,10,12,10,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,3,3,3,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,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,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,3,4,13,3,6,3,3,13,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,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,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,12,11,11,11,11,11,11,11,3,3,3,3,6,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,12,12,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,12,12,12,11,11,11,11,11,11,11,11,4,3,3,13,13,3,3,3,3,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,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,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,12,12,11,11,12,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11],"n":["Anchor","AnchorFromBlockPosition","Append","BIP32_MAX_INDEX","BlockId","COINBASE_MATURITY","ChainOracle","ChainPosition","ConfirmationHeightAnchor","ConfirmationTime","ConfirmationTimeHeightAnchor","Confirmed","Confirmed","DescriptorExt","DescriptorId","Error","FullTxOut","IndexedTxGraph","SpkIterator","SpkTxOutIndex","TxGraph","Unconfirmed","Unconfirmed","all_spks","all_zeros","anchor_block","anchor_block","anchor_block","anchor_block","anchor_block","anchor_block","append","apply_changeset","as_byte_array","as_raw_hash","as_ref","as_ref","bitcoin","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","chain_position","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cloned","cmp","cmp","cmp","cmp","cmp","cmp","cmp","confirmation_height","confirmation_height","confirmation_height_upper_bound","confirmation_height_upper_bound","confirmation_height_upper_bound","confirmation_height_upper_bound","confirmation_height_upper_bound","confirmation_time","default","default","default","default","descriptor","descriptor_id","deserialize","deserialize","deserialize","deserialize","deserialize","dust_value","engine","eq","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from_block_position","from_block_position","from_block_position","from_block_position","from_byte_array","from_engine","from_raw_hash","from_slice","from_slice_delegated","from_str","get_chain_tip","hash","hash","hash","hash","hash","hash","hash","height","index","index_of_spk","index_tx","index_txout","indexed_tx_graph","initial_changeset","insert_spk","into","into","into","into","into","into","into","into","into","into_iter","is_block_in_chain","is_confirmed","is_confirmed","is_confirmed_and_spendable","is_empty","is_mature","is_on_coinbase","is_relevant","is_tx_relevant","is_used","keychain","local_chain","mark_used","miniscript","net_value","new","new_with_range","next","nth","outpoint","outpoints","outputs_in_range","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","scan","scan_txout","sent_and_received","serialize","serialize","serialize","serialize","serialize","spent_by","spk_at_index","spk_client","to_byte_array","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_raw_hash","to_string","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","tx_graph","txout","txout","txouts","txouts_in_tx","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unconfirmed","unmark_used","unused_spks","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","height","last_seen","time","ChangeSet","ChangeSet","IndexedTxGraph","Indexer","append","apply_block","apply_block_relevant","apply_changeset","apply_changeset","apply_update","batch_insert_relevant","batch_insert_relevant_unconfirmed","batch_insert_unconfirmed","borrow","borrow","borrow_mut","borrow_mut","clone","clone_into","default","default","deserialize","eq","fmt","fmt","from","from","from","from","graph","graph","index","index_tx","index_txout","indexer","initial_changeset","initial_changeset","insert_anchor","insert_seen_at","insert_tx","insert_txout","into","into","is_empty","is_tx_relevant","new","serialize","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","Balance","ChangeSet","KeychainTxOutIndex","add","all_unbounded_spk_iters","append","apply_changeset","apply_changeset","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone_into","clone_into","clone_into","confirmed","default","default","default","deserialize","deserialize","eq","eq","fmt","fmt","fmt","fmt","from","from","from","get_descriptor","immature","index_of_spk","index_tx","index_txout","initial_changeset","inner","insert_descriptor","into","into","into","is_empty","is_tx_relevant","is_used","keychain_outpoints","keychain_outpoints_in_range","keychains","keychains_added","last_revealed","last_revealed_index","last_revealed_indices","last_used_index","last_used_indices","lookahead","lookahead_to_target","mark_used","net_value","new","next_index","next_unused_spk","outpoints","reveal_next_spk","reveal_to_target","reveal_to_target_multi","revealed_keychain_spks","revealed_spks","sent_and_received","serialize","serialize","spk_at_index","to_owned","to_owned","to_owned","to_string","total","trusted_pending","trusted_spendable","try_from","try_from","try_from","try_into","try_into","try_into","txout","txouts","txouts_in_tx","type_id","type_id","type_id","unbounded_spk_iter","unmark_used","untrusted_pending","unused_keychain_spks","unused_spks","vzip","vzip","vzip","AlterCheckPointError","ApplyHeaderError","CannotConnect","CannotConnectError","ChangeSet","CheckPoint","CheckPointIter","InconsistentBlocks","LocalChain","MissingGenesisError","apply_changeset","apply_header","apply_header_connected_to","apply_update","block_id","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","disconnect_from","eq","eq","eq","eq","eq","eq","extend","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from_block_ids","from_blocks","from_changeset","from_genesis_hash","from_header","from_tip","genesis_hash","get","get","get_chain_tip","hash","height","height","initial_changeset","insert","insert_block","into","into","into","into","into","into","into","into_iter","into_iter","is_block_in_chain","iter","iter_checkpoints","new","next","original_hash","prev","provide","provide","provide","provide","push","range","range","tip","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_include_height","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_hash","vzip","vzip","vzip","vzip","vzip","vzip","vzip","FullScanRequest","FullScanResult","SyncRequest","SyncResult","TxCache","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","cache_graph_txs","cache_graph_txs","cache_txs","cache_txs","chain_outpoints","chain_spks","chain_spks_for_keychain","chain_tip","chain_tip","chain_txids","chain_update","chain_update","from","from","from","from","from_chain_tip","from_chain_tip","from_keychain_txout_index","graph_update","graph_update","inspect_outpoints","inspect_spks","inspect_spks_for_all_keychains","inspect_spks_for_keychain","inspect_txids","into","into","into","into","last_active_indices","outpoints","populate_with_revealed_spks","set_outpoints","set_spks","set_spks_for_keychain","set_txids","spks","spks_by_keychain","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","tx_cache","tx_cache","txids","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","CalculateFeeError","CanonicalTx","ChangeSet","MissingTxOut","NegativeFee","TxAncestors","TxDescendants","TxGraph","TxNode","all_anchors","all_txouts","anchor_heights","anchors","anchors","append","apply_changeset","apply_update","as_ref","balance","batch_insert_unconfirmed","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","calculate_fee","chain_position","checked_sum","checked_sum","checked_sum","checked_sum","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","cmp","default","default","deref","deserialize","direct_conflicts","eq","eq","eq","eq","eq","filter_chain_txouts","filter_chain_unspents","floating_txouts","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","full_txs","get_chain_position","get_chain_spend","get_tx","get_tx_node","get_txout","initial_changeset","insert_anchor","insert_seen_at","insert_tx","insert_txout","into","into","into","into","into","into","into","into_iter","into_iter","is_empty","is_empty","last_seen","last_seen_unconfirmed","list_chain_txs","map_anchors","map_anchors","new","next","next","outspends","partial_cmp","partial_cmp","provide","serialize","to_owned","to_owned","to_owned","to_owned","to_string","try_balance","try_filter_chain_txouts","try_filter_chain_unspents","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_get_chain_position","try_get_chain_spend","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_list_chain_txs","tx","tx_node","tx_outputs","tx_spends","txid","txouts","txouts","txs","type_id","type_id","type_id","type_id","type_id","type_id","type_id","update_last_seen_unconfirmed","vzip","vzip","vzip","vzip","vzip","vzip","vzip","walk_ancestors","walk_conflicts","walk_descendants"],"q":["bdk_chain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::ConfirmationTime","","","bdk_chain::indexed_tx_graph","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::keychain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::local_chain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::spk_client","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::tx_graph","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Trait that “anchors” blockchain data to a specific …","An Anchor that can be constructed from a given block, …","Trait that makes an object appendable.","Maximum BIP32 derivation index.","A reference to a block in the canonical chain.","How many confirmations are needed f or a coinbase output …","Represents a service that tracks the blockchain.","Represents the observed position of some chain data.","An Anchor implementation that also records the exact …","Block height and timestamp at which a transaction is …","An Anchor implementation that also records the exact …","The chain data is seen as confirmed, and in anchored by A.","The transaction is confirmed","A trait to extend the functionality of a miniscript …","Represents the ID of a descriptor, defined as the sha256 …","Error type.","A TxOut with as much data as we can retrieve about it","","An iterator for derived script pubkeys.","An index storing TxOuts that have a script pubkey that …","","The chain data is not confirmed and last seen in the …","The transaction is unconfirmed","The script pubkeys that are being tracked by the index.","","Returns the BlockId that the associated blockchain data is …","","","","The anchor block.","The anchor block.","Append another object of the same type onto self.","","","Returns a reference to the inner hash (sha256, sh256d …","","","","","","","","","","","","","","","","","","","","","","","The position of the transaction in outpoint in the overall …","","","","","","","","","","","","","","","","","","","Maps a ChainPosition<&A> into a ChainPosition<A> by …","","","","","","","","The exact confirmation height of the transaction.","The confirmation height of the transaction being anchored.","Get the upper bound of the chain data’s confirmation …","Get the upper bound of the chain data’s confirmation …","Determines the upper bound of the confirmation height.","","","The confirmation time of the transaction being anchored.","","","","","Get a reference to the internal descriptor.","Returns the descriptor id, calculated as the sha256 of the …","","","","","","Returns the minimum value (in satoshis) at which an output …","","","","","","","","","","","","","","","","","","","","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.","Construct the anchor from a given block, block height and …","","","","","","Creates this wrapper type from the inner hash type.","","","","Get the best chain’s chain tip.","","","","","","","The hash of the block.","The height of the block.","","Returns the index associated with the script pubkey.","","","Contains the IndexedTxGraph and associated types. Refer to …","","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).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","Determines whether block of BlockId exists as an ancestor …","Returns whether ChainPosition is confirmed or not.","Returns whether ConfirmationTime is the confirmed variant.","Whether the utxo is/was/will be spendable with chain tip.","Returns whether the structure is considered empty.","Whether the txout is considered mature.","Whether this output is on a coinbase transaction.","Whether any of the inputs of this transaction spend a …","","Returns whether the script pubkey at index has been used …","Module for keychain related structures.","The LocalChain is a local implementation of ChainOracle.","Marks the script pubkey at index as used even though it …","","Computes the net value transfer effect of tx on the script …","Create a new script pubkey iterator from descriptor.","Create a new script pubkey iterator from descriptor and a …","","","The location of the TxOut.","Get a reference to the set of indexed outpoints.","Iterates over all the outputs with script pubkeys in an …","","","","","","","","Scans a transaction’s outputs for matching script …","Scan a single TxOut for a matching script pubkey and …","Computes the total value transfer effect tx has on the …","","","","","","The txid and chain position of the transaction (if any) …","Returns the script that has been inserted at the index.","Helper types for spk-based blockchain clients.","","","","","","","","","","","Returns the inner hash (sha256, sh256d etc.).","","","","","","","","","","","","","","","","","","","","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 …","","","","","","","","","","Construct an unconfirmed variant using the given last_seen …","Undoes the effect of mark_used. Returns whether the index …","Iterates over all unused script pubkeys in an index range.","","","","","","","","","","Confirmation height.","The last-seen timestamp in unix seconds.","Confirmation time in unix seconds.","Represents changes to an IndexedTxGraph.","The resultant “changeset” when new transaction data is …","The IndexedTxGraph combines a TxGraph and an Indexer …","Utilities for indexing transaction data.","","Batch insert all transactions of the given block of height.","Batch insert all transactions of the given block of height…","Apply changeset to itself.","Applies the ChangeSet to the IndexedTxGraph.","Apply an update directly.","Batch insert transactions, filtering out those that are …","Batch insert unconfirmed transactions, filtering out those …","Batch insert unconfirmed transactions.","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","","Get a reference of the internal transaction graph.","TxGraph changeset.","Transaction index.","Scans a transaction for relevant outpoints, which are …","Scan and index the given outpoint and txout.","Indexer changeset.","Determines the ChangeSet between self and an empty Indexer.","Determines the ChangeSet between self and an empty …","Insert an anchor for a given transaction.","Insert a unix timestamp of when a transaction is seen in …","Insert and index a transaction into the graph.","Insert a floating txout of given outpoint.","Calls U::from(self).","Calls U::from(self).","","Determines whether the transaction should be included in …","Construct a new IndexedTxGraph with a given index.","","","","","","","","","","","Balance, differentiated into various categories.","Represents updates to the derivation index of a …","KeychainTxOutIndex controls how script pubkeys are …","","Get unbounded spk iterators for all keychains.","Append another ChangeSet into self.","Applies the derivation changeset to the KeychainTxOutIndex…","","","","","","","","","","","","","","Confirmed and immediately spendable balance","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Gets the descriptor associated with the keychain. Returns …","All coinbase outputs not yet matured","Returns the keychain and keychain index associated with …","","","","Return a reference to the internal SpkTxOutIndex.","Insert a descriptor with a keychain associated to it.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Returns whether the changeset are empty.","","Returns whether the spk under the keychain’s index has …","Iterate over all OutPoints that have TxOuts with script …","Iterate over OutPoints that have script pubkeys derived …","Return the map of the keychain to descriptors.","Contains the keychains that have been added and their …","Contains for each descriptor_id the last revealed index of …","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 …","Get the lookahead setting.","Store lookahead scripts until target_index (inclusive).","Marks the script pubkey at index as used even though the …","Computes the net value that this transaction gives to the …","Construct a KeychainTxOutIndex with the given lookahead.","Get the next derivation index for keychain. The next index …","Gets the next unused script pubkey in the keychain. I.e., …","Get the set of indexed outpoints, corresponding to tracked …","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 …","Iterate over revealed spks of the given keychain.","Iterate over revealed spks of keychains in range","Computes the total value transfer effect tx has on the …","","","Return the script that exists under the given keychain’s …","","","","","Get the whole balance visible to the wallet.","Unconfirmed UTXOs generated by a wallet tx","Get sum of trusted_pending and confirmed coins.","","","","","","","Return the TxOut of outpoint if it has been indexed, and …","Iterate over known txouts that spend to tracked script …","Finds all txouts on a transaction that has previously been …","","","","Get an unbounded spk iterator over a given keychain. …","Undoes the effect of mark_used. Returns whether the index …","Unconfirmed UTXOs received from an external wallet","Iterate over revealed, but unused, spks of the given …","Iterate over revealed, but unused, spks of all keychains.","","","","Represents a failure when trying to insert/remove a …","The error type for LocalChain::apply_header_connected_to.","Occurs when the update cannot connect with the original …","Occurs when an update does not have a common checkpoint …","The ChangeSet represents changes to LocalChain.","A LocalChain checkpoint is used to find the agreement …","Iterates over checkpoints backwards.","Occurs when connected_to block conflicts with either the …","This is a local implementation of ChainOracle.","An error which occurs when a LocalChain is constructed …","Apply the given changeset.","Update the chain with a given Header connecting it with …","Update the chain with a given Header at height which you …","Applies the given update to the chain.","Get the BlockId of the checkpoint.","","","","","","","","","","","","","","","","","","","","","","","","","","","Removes blocks from (and inclusive of) the given block_id.","","","","","","","Extends the checkpoint linked list by a iterator of block …","","","","","","","","","","","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.","Construct a checkpoint from a list of BlockIds in …","Constructs a LocalChain from a BTreeMap of height to …","Construct a LocalChain from an initial changeset.","Construct LocalChain from genesis hash.","Construct a checkpoint from the given header and block …","Construct a LocalChain from a given checkpoint tip.","Get the genesis hash.","Get checkpoint at height.","Get checkpoint at given height (if it exists).","","Get the block hash of the checkpoint.","Get the height of the checkpoint.","The checkpoint’s height.","Derives an initial ChangeSet, meaning that it can be …","Inserts block_id at its height within the chain.","Insert a BlockId.","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).","","","","Iterate from this checkpoint in descending height.","Iterate over checkpoints in descending height order.","Construct a new base block at the front of a linked list.","","The original checkpoint’s block hash which cannot be …","Get the previous checkpoint in the chain","","","","","Puts another checkpoint onto the linked list representing …","Iterate checkpoints over a height range.","Iterate checkpoints over a height range.","Get the highest checkpoint.","","","","","","","","","","","","","","","","","","The suggested checkpoint to include to connect the two …","","","","","","","","","","","","","","","The attempted update to the original_block hash.","","","","","","","","Data required to perform a spk-based blockchain client …","Data returned from a spk-based blockchain client full scan.","Data required to perform a spk-based blockchain client …","Data returned from a spk-based blockchain client sync.","A cache of Arc-wrapped full transactions, identified by …","","","","","","","","","Add all transactions from TxGraph into the TxCache.","Add all transactions from TxGraph into the TxCache.","Add to the TxCache held by the request.","Add to the TxCache held by the request.","Chain on additional OutPoints that will be synced against.","Chain on additional Scripts that will be synced against.","Chain on additional Scripts that will be synced against.","A checkpoint for the current chain LocalChain::tip. The …","A checkpoint for the current LocalChain::tip. The full …","Chain on additional Txids that will be synced against.","The update to apply to the receiving LocalChain.","The update to apply to the receiving TxGraph.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Construct a new SyncRequest from a given cp tip.","Construct a new FullScanRequest from a given chain_tip.","Construct a new FullScanRequest from a given chain_tip and …","The update to apply to the receiving TxGraph.","The update to apply to the receiving LocalChain.","Add a closure that will be called for OutPoints previously …","Add a closure that will be called for Scripts previously …","Add a closure that will be called for every Script …","Add a closure that will be called for every Script …","Add a closure that will be called for Txids previously …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Last active indices for the corresponding keychains (K).","Transactions with these outpoints or spent from these …","Populate the request with revealed script pubkeys from …","Set the OutPoints that will be synced against.","Set the Scripts that will be synced against.","Set the Scripts for a given keychain.","Set the Txids that will be synced against.","Transactions that spend from or to these indexed script …","Iterators of script pubkeys indexed by the keychain index.","","","","","","","","","Cache of full transactions, so the chain-source can avoid …","Cache of full transactions, so the chain-source can avoid …","Transactions with these txids.","","","","","","","","","Errors returned by TxGraph::calculate_fee.","A transaction that is included in the chain, or is still …","The ChangeSet represents changes to a TxGraph.","Missing TxOut for one or more of the inputs of the tx","When the transaction is invalid according to the graph it …","An iterator that traverses ancestors of a given root …","An iterator that traverses transaction descendants.","A graph of transactions and spends.","A transaction node in the TxGraph.","Get all transaction anchors known by TxGraph.","Iterate over all tx outputs known by TxGraph.","Iterates over the heights of that the new transaction …","The blocks that the transaction is “anchored” in.","Added anchors.","","Applies ChangeSet to TxGraph.","Extends this graph with another so that self becomes the …","","Get the total balance of outpoints that are in chain of …","Batch insert unconfirmed transactions.","","","","","","","","","","","","","","","Calculates the fee of a given transaction. Returns 0 if tx …","How the transaction is observed as (confirmed or …","","","","","","","","","","","","","","","","","","","Given a transaction, return an iterator of txids that …","","","","","","Get a filtered list of outputs from the given outpoints …","Get a filtered list of unspent outputs (UTXOs) from the …","Iterate over floating txouts known by TxGraph.","","","","","","","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.","Iterate over all full transactions in the graph.","Get the position of the transaction in chain with tip …","Get the txid of the spending transaction and where the …","Get a transaction by txid. This only returns Some for full …","Get a transaction node by txid. This only returns Some for …","Obtains a single tx output (if any) at the specified …","Determines the ChangeSet between self and an empty TxGraph.","Inserts the given anchor into TxGraph.","Inserts the given seen_at for txid into TxGraph.","Inserts the given transaction into TxGraph.","Inserts the given TxOut at OutPoint.","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 the graph has any transactions or outputs in it.","","Added last-seen unix timestamps of transactions.","The last-seen unix timestamp of the transaction as …","List graph transactions that are in chain with chain_tip.","Transform the TxGraph to have Anchors of another type.","Transform the ChangeSet to have Anchors of another type.","Construct a new TxGraph from a list of transactions.","","","The transactions spending from this output.","","","","","","","","","","Get the total balance of outpoints that are in chain of …","Get a filtered list of outputs from the given outpoints …","Get a filtered list of unspent outputs (UTXOs) from the …","","","","","","","","Get the position of the transaction in chain with tip …","Get the txid of the spending transaction and where the …","","","","","","","","List graph transactions that are in chain with chain_tip.","A partial or full representation of the transaction.","The transaction node (as part of the graph).","Returns known outputs of a given txid.","Iterates over the transactions spending from txid.","Txid of the transaction.","Iterates over all outpoints contained within ChangeSet.","Added txouts.","Added transactions.","","","","","","","","Update the last seen time for all unconfirmed transactions.","","","","","","","","Creates an iterator that filters and maps ancestor …","Creates an iterator that both filters and maps conflicting …","Creates an iterator that filters and maps descendants from …"],"i":[0,0,0,0,0,0,0,0,0,0,0,10,11,0,0,86,0,0,0,0,0,10,11,3,5,16,6,7,8,7,8,47,3,5,5,5,5,0,3,10,11,6,7,8,12,5,5,13,3,10,11,6,7,8,12,5,13,12,3,10,11,6,7,8,12,5,13,3,10,11,6,7,8,12,5,13,10,10,11,6,7,8,12,5,7,8,16,16,10,7,8,8,3,6,7,8,13,87,11,6,7,8,5,87,5,10,11,6,7,8,12,5,3,10,11,6,7,8,12,5,5,5,5,3,10,11,11,6,6,6,7,8,12,5,5,13,88,6,7,8,5,5,5,5,5,5,86,10,11,6,7,8,5,6,6,5,3,3,3,0,3,3,3,10,11,6,7,8,12,5,13,13,86,10,11,12,47,12,12,3,3,3,0,0,3,0,3,13,13,13,13,12,3,3,10,11,6,7,8,12,5,3,3,3,11,6,7,8,5,12,3,0,5,3,10,11,6,7,8,12,5,13,5,5,3,10,11,6,7,8,12,5,13,3,10,11,6,7,8,12,5,13,0,3,12,3,3,3,10,11,6,7,8,12,5,13,11,3,3,3,10,11,6,7,8,12,5,13,89,90,89,0,49,0,0,48,50,50,49,50,50,50,50,50,50,48,50,48,48,48,50,48,48,48,50,48,50,48,48,48,50,48,50,49,49,48,49,50,50,50,50,50,50,48,48,49,50,48,48,50,48,50,48,50,48,50,48,0,0,0,56,57,54,57,57,54,57,56,54,57,56,54,57,56,54,57,56,56,54,57,56,54,56,54,56,54,57,56,56,54,57,56,57,56,57,57,57,57,57,57,54,57,56,54,57,57,57,57,57,54,54,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,57,54,56,57,54,57,56,56,56,56,56,54,57,56,54,57,56,57,57,57,54,57,56,57,57,56,57,57,54,57,56,0,0,66,0,0,0,0,66,0,0,61,61,61,61,67,70,67,61,63,68,65,66,70,67,61,63,68,65,66,67,61,63,68,65,66,67,61,63,68,65,66,61,67,61,63,68,65,66,67,67,61,63,63,68,68,65,65,66,66,70,67,61,63,68,65,66,67,61,61,61,67,61,61,67,61,61,67,67,68,61,67,61,70,67,61,63,68,65,66,70,67,61,67,61,67,70,68,67,63,68,65,66,67,67,61,61,67,61,63,68,65,66,63,68,65,66,70,67,61,63,68,65,66,65,70,67,61,63,68,65,66,70,67,61,63,68,65,66,68,70,67,61,63,68,65,66,0,0,0,0,0,73,91,74,92,73,91,74,92,73,74,73,74,73,73,74,73,74,73,91,92,73,91,74,92,73,74,74,91,92,73,73,74,74,73,73,91,74,92,92,73,73,73,73,74,73,73,74,73,91,74,92,73,91,74,92,73,74,73,73,91,74,92,73,91,74,92,0,0,0,78,78,0,0,0,0,51,51,55,79,55,55,51,51,51,51,51,83,84,51,79,80,78,55,83,84,51,79,80,78,55,51,80,83,83,84,84,51,79,80,55,51,79,80,55,79,80,51,55,79,55,51,51,79,80,78,55,51,51,51,51,79,80,78,78,55,83,84,51,79,80,78,55,51,51,51,51,51,51,51,51,51,51,51,83,84,51,79,80,78,55,83,84,51,55,55,79,51,51,55,51,83,84,51,79,80,78,55,51,79,80,55,78,51,51,51,83,84,51,79,80,78,55,51,51,83,84,51,79,80,78,55,51,79,80,51,51,79,55,55,55,83,84,51,79,80,78,55,51,83,84,51,79,80,78,55,51,51,51],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[[3,[[0,[1,2]]]]],4],[[],5],[[],6],[6,6],[7,6],[8,6],0,0,[[]],[[[3,[[0,[1,2]]]]]],[5],[5,9],[5],[5],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[5],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[[3,[1]]],[[3,[1]]]],[[[10,[1]]],[[10,[1]]]],[11,11],[6,6],[7,7],[8,8],[[[12,[1]]],[[12,[1]]]],[5,5],[[[13,[1]]],[[13,[1]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[10,[[10,[1]]]],[[[10,[2]],10],14],[[11,11],14],[[6,6],14],[[7,7],14],[[8,8],14],[[[12,[2]],12],14],[[5,5],14],0,0,[[],15],[[],15],[[[10,[16]]],[[17,[15]]]],[7,15],[8,15],0,[[],3],[[],6],[[],7],[[],8],[13],[[],5],[[],[[18,[11]]]],[[],[[18,[6]]]],[[],[[18,[7]]]],[[],[[18,[8]]]],[19,[[18,[5]]]],[[],20],[[]],[[[10,[21]],10],22],[[11,11],22],[[6,6],22],[[7,7],22],[[8,8],22],[[[12,[21]],12],22],[[5,5],22],[[[3,[23]],24],25],[[[10,[23]],24],25],[[11,24],25],[[6,24],25],[[7,24],25],[[8,24],25],[[[12,[23]],24],25],[[5,24],25],[[5,24],25],[[5,24],25],[[5,24],25],[[]],[[]],[[[10,[8]]],11],[[]],[[]],[[],6],[[],6],[[]],[[]],[[]],[9,5],[[]],[[]],[[26,6,27]],[[26,6,27],6],[[26,6,27],7],[[26,6,27],8],[[],5],[[],5],[9,5],[[],[[18,[5,28]]]],[[],[[18,[5,28]]]],[29,[[18,[5]]]],[[],[[18,[6]]]],[[[10,[30]]]],[11],[6],[7],[8],[5],0,0,[[5,31]],[[[3,[[0,[1,2]]]],32],17],[[[3,[[0,[1,2]]]],33]],[[[3,[[0,[1,2]]]],34,35]],0,[[[3,[[0,[1,2]]]]]],[[[3,[[0,[1,2]]]],[0,[1,2]],36],22],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[6,6],[[18,[[17,[22]]]]]],[10,22],[11,22],[[[12,[16]],15],22],[[],22],[[[12,[16]],15],22],0,[[[3,[[0,[1,2]]]],33],22],[[[3,[[0,[1,2]]]],33],22],[[[3,[[0,[1,2]]]]],22],0,0,[[[3,[[0,[1,2]]]]],22],0,[[[3,[[0,[1,2]]]],33,[37,[[0,[1,2]]]]],38],[[],13],[[],13],[13,17],[[13,27],17],0,[[[3,[[0,[1,2]]]]],39],[[[3,[[0,[1,2]]]],[37,[[0,[1,2]]]]],40],[[[10,[41]],10],[[17,[14]]]],[[11,11],[[17,[14]]]],[[6,6],[[17,[14]]]],[[7,7],[[17,[14]]]],[[8,8],[[17,[14]]]],[[[12,[41]],12],[[17,[14]]]],[[5,5],[[17,[14]]]],[[[3,[[0,[1,2]]]],33],[[39,[[0,[1,2]]]]]],[[[3,[[0,[1,2]]]],34,35],17],[[[3,[[0,[1,2]]]],33,[37,[[0,[1,2]]]]]],[11,18],[6,18],[7,18],[8,18],[[5,42],18],0,[[[3,[[0,[1,2]]]]],[[17,[32]]]],0,[5],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[5,9],[[],43],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],0,[[[3,[[0,[1,2]]]],34],17],0,[[[3,[[0,[1,2]]]]],[[0,[40,44]]]],[[[3,[[0,[1,2]]]],45],40],[[],46],[[],46],[[],46],[[],46],[[],46],[[],46],[[],46],[[],46],[[],46],[20,11],[[[3,[[0,[1,2]]]]],22],[[[3,[[0,[1,2]]]]],[[0,[40,1]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,[[[48,[16,47]],[48,[16,47]]]],[[[50,[49]],26,15],48],[[[50,[49]],26,15],48],[[]],[[[50,[16,49]],[48,[16]]]],[[[50,[16,49]],[51,[16]]],[[48,[16]]]],[[[50,[16,49]],52],[[48,[16]]]],[[[50,[16,49]],52],[[48,[16]]]],[[[50,[16,49]],52],[[48,[16]]]],[[]],[[]],[[]],[[]],[[[48,[1,1]]],[[48,[1,1]]]],[[]],[[],[[50,[53]]]],[[],[[48,[53]]]],[[],[[18,[48]]]],[[[48,[21,21]],48],22],[[[50,[23,23]],24],25],[[[48,[23,23]],24],25],[[]],[[]],[54,[[48,[54]]]],[55,[[48,[53]]]],[50,51],0,0,[33],[[34,35]],0,[[]],[[[50,[16,49]]],[[48,[16]]]],[[[50,[16,49]],45,16],[[48,[16]]]],[[[50,[16,49]],45,20],[[48,[16]]]],[[[50,[16,49]],33],[[48,[16]]]],[[[50,[16,49]],34,35],[[48,[16]]]],[[]],[[]],[[[48,[16,47]]],22],[33,22],[[],50],[48,18],[[]],[[],18],[[],18],[[],18],[[],18],[[],46],[[],46],[[]],[[]],0,0,0,[[56,56],56],[[[57,[[0,[1,2,23]]]]],[[4,[[0,[1,2,23]],[13,[[59,[58]]]]]]]],[[[54,[2]],[54,[2]]]],[[[57,[[0,[1,2,23]]]],[54,[[0,[1,2,23]]]]]],[[[57,[[0,[1,2,23]]]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[[54,[1]]],[[54,[1]]]],[[[57,[1]]],[[57,[1]]]],[56,56],[[]],[[]],[[]],0,[[],54],[[],57],[[],56],[[],[[18,[54]]]],[[],[[18,[56]]]],[[[54,[21]],54],22],[[56,56],22],[[[54,[23]],24],25],[[[57,[23]],24],25],[[56,24],25],[[56,24],25],[[]],[[]],[[]],[[[57,[[0,[1,2,23]]]]],[[17,[59]]]],0,[[[57,[[0,[1,2,23]]]],32],17],[[[57,[[0,[1,2,23]]]],33]],[[[57,[[0,[1,2,23]]]],34,35]],[[[57,[[0,[1,2,23]]]]]],[[[57,[[0,[1,2,23]]]]],3],[[[57,[[0,[1,2,23]]]],[0,[1,2,23]],[59,[58]]],[[54,[[0,[1,2,23]]]]]],[[]],[[]],[[]],[[[54,[2]]],22],[[[57,[[0,[1,2,23]]]],33],22],[[[57,[[0,[1,2,23]]]],[0,[1,2,23]],15],22],[[[57,[[0,[1,2,23]]]]],40],[[[57,[[0,[1,2,23]]]],[37,[[0,[1,2,23]]]]],40],[[[57,[[0,[1,2,23]]]]],[[0,[40,44]]]],0,0,[[[57,[[0,[1,2,23]]]]],[[17,[15]]]],[[[57,[[0,[1,2,23]]]]],[[4,[[0,[1,2,23]],15]]]],[[[57,[[0,[1,2,23]]]]],[[17,[15]]]],[[[57,[[0,[1,2,23]]]]],[[4,[[0,[1,2,23]],15]]]],[[[57,[[0,[1,2,23]]]]],15],[[[57,[[0,[1,2,23]]]],15]],[[[57,[[0,[1,2,23]]]],[0,[1,2,23]],15],22],[[[57,[[0,[1,2,23]]]],33,[37,[[0,[1,2,23]]]]],38],[15,57],[[[57,[[0,[1,2,23]]]]],17],[[[57,[[0,[1,2,23]]]]],17],[[[57,[[0,[1,2,23]]]]],40],[[[57,[[0,[1,2,23]]]]],17],[[[57,[[0,[1,2,23]]]],15],17],[[[57,[[0,[1,2,23]]]],4]],[[[57,[[0,[1,2,23]]]]],40],[[[57,[[0,[1,2,23]]]],[37,[[0,[1,2,23]]]]],[[0,[40,1]]]],[[[57,[[0,[1,2,23]]]],33,[37,[[0,[1,2,23]]]]]],[54,18],[56,18],[[[57,[[0,[1,2,23]]]],[0,[1,2,23]],15],[[17,[32]]]],[[]],[[]],[[]],[[],43],[56,60],0,[56,60],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[[57,[[0,[1,2,23]]]],34],17],[[[57,[[0,[1,2,23]]]]],40],[[[57,[[0,[1,2,23]]]],45],40],[[],46],[[],46],[[],46],[[[57,[[0,[1,2,23]]]]],[[17,[[13,[[59,[58]]]]]]]],[[[57,[[0,[1,2,23]]]],[0,[1,2,23]],15],22],0,[[[57,[[0,[1,2,23]]]]],[[0,[40,1]]]],[[[57,[[0,[1,2,23]]]]],[[0,[40,1]]]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,[[61,62],[[18,[63]]]],[[61,64,15],[[18,[62,65]]]],[[61,64,15,6],[[18,[62,66]]]],[[61,67],[[18,[62,65]]]],[67,6],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[67,67],[61,61],[63,63],[68,68],[65,65],[66,66],[[]],[[]],[[]],[[]],[[]],[[]],[[61,6],[[18,[62,63]]]],[[67,67],22],[[61,61],22],[[63,63],22],[[68,68],22],[[65,65],22],[[66,66],22],[[67,52],[[18,[67,67]]]],[[67,24],25],[[61,24],25],[[63,24],25],[[63,24],25],[[68,24],25],[[68,24],25],[[65,24],25],[[65,24],25],[[66,24],25],[[66,24],25],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[52,[[18,[67,[17,[67]]]]]],[[[4,[15,69]]],[[18,[61,63]]]],[62,[[18,[61,63]]]],[69],[[64,15],67],[67,[[18,[61,63]]]],[61,69],[[67,15],[[17,[67]]]],[[61,15],[[17,[67]]]],[61,[[18,[6]]]],[67,69],[67,15],0,[61,62],[[67,6],67],[[61,6],[[18,[62,68]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[67],[[61,6,6],[[18,[[17,[22]]]]]],[67,70],[61,70],[6,67],[70,17],0,[67,[[17,[67]]]],[71],[71],[71],[71],[[67,6],[[18,[67,67]]]],[67,72],[61,72],[61,67],[[]],[[]],[[]],[[]],[[]],[[]],[[],43],[[],43],[[],43],[[],43],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],0,[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],46],[[],46],[[],46],[[],46],[[],46],[[],46],[[],46],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[73,51],73],[[[74,[[0,[2,1]]]],51],[[74,[[0,[2,1]]]]]],[[73,52],73],[[[74,[[0,[2,1]]]],52],[[74,[[0,[2,1]]]]]],[[73,52],73],[[73,52],73],[[[74,[[0,[2,1]]]],[0,[2,1]],52],[[74,[[0,[2,1]]]]]],0,0,[[73,52],73],0,0,[[]],[[]],[[]],[[]],[67,73],[67,[[74,[[0,[2,1]]]]]],[[67,57],[[74,[[0,[2,1]]]]]],0,0,[[73,[0,[75,76,77]]],73],[[73,[0,[75,76,77]]],73],[[[74,[[0,[2,1]]]],[0,[75,76,77,1]]],[[74,[[0,[2,1]]]]]],[[[74,[[0,[2,1]]]],[0,[2,1]],[0,[75,76,77]]],[[74,[[0,[2,1]]]]]],[[73,[0,[75,76,77]]],73],[[]],[[]],[[]],[[]],0,0,[[73,57,[37,[[0,[1,2,23,76,77]]]]],73],[[73,52],73],[[73,52],73],[[[74,[[0,[2,1]]]],[0,[2,1]],52],[[74,[[0,[2,1]]]]]],[[73,52],73],0,0,[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],0,0,0,[[],46],[[],46],[[],46],[[],46],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,[51,39],[51,72],[55,72],0,0,[[[55,[2]],[55,[2]]]],[[[51,[[0,[1,2]]]],[55,[[0,[1,2]]]]]],[[[51,[[0,[1,2]]]],[51,[[0,[1,2]]]]],[[55,[[0,[1,2]]]]]],[51,51],[[[51,[16]],6,52,75],56],[[[51,[[0,[1,2]]]],52],[[55,[[0,[1,2]]]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[51,33],[[18,[20,78]]]],0,[[],[[17,[38]]]],[[],[[17,[60]]]],[[],[[17,[60]]]],[[],[[17,[38]]]],[[[51,[1]]],[[51,[1]]]],[[[79,[1,1]]],[[79,[1,1]]]],[[[80,[1,1]]],[[80,[1,1]]]],[[[55,[1]]],[[55,[1]]]],[[]],[[]],[[]],[[]],[[[79,[2,2]],79],14],[[[80,[2,2]],80],14],[[],51],[[],55],[79],[[],[[18,[55]]]],[[51,33],72],[[[51,[21]],51],22],[[[79,[21,21]],79],22],[[[80,[21,21]],80],22],[[78,78],22],[[[55,[21]],55],22],[[[51,[16]],6,52],72],[[[51,[16]],6,52],72],[51,72],[[[51,[23]],24],25],[[[79,[23,23]],24],25],[[[80,[23,23]],24],25],[[78,24],25],[[78,24],25],[[[55,[23]],24],25],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[51,72],[[[51,[16]],6,45],[[17,[10]]]],[[[51,[16]],6,34],17],[[51,45],[[17,[[81,[33]]]]]],[[51,45],[[17,[[79,[[81,[33]]]]]]]],[[51,34],[[17,[35]]]],[[[51,[[0,[1,2]]]]],[[55,[[0,[1,2]]]]]],[[[51,[[0,[1,2]]]],45,[0,[1,2]]],[[55,[[0,[1,2]]]]]],[[[51,[[0,[1,2]]]],45,20],[[55,[[0,[1,2]]]]]],[[[51,[[0,[1,2]]]],[82,[[81,[33]]]]],[[55,[[0,[1,2]]]]]],[[[51,[[0,[1,2]]]],34,35],[[55,[[0,[1,2]]]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[51,22],[[[55,[2]]],22],0,0,[[[51,[16]],6],72],[[[51,[[0,[1,2]]]]],[[51,[[0,[1,2]]]]]],[[[55,[2]]],[[55,[2]]]],[52,[[51,[[0,[1,2]]]]]],[83,17],[84,17],[[51,34],85],[[[79,[41,41]],79],[[17,[14]]]],[[[80,[41,41]],80],[[17,[14]]]],[71],[55,18],[[]],[[]],[[]],[[]],[[],43],[[[51,[16]],6,52,75],[[18,[56]]]],[[[51,[16]],6,52],72],[[[51,[16]],6,52],72],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[[51,[16]],6,45],[[18,[[17,[10]]]]]],[[[51,[16]],6,34],[[18,[17]]]],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[],18],[[[51,[16]],6],72],0,0,[[51,45],[[17,[[4,[15,35]]]]]],[[51,45],40],0,[55,72],0,0,[[],46],[[],46],[[],46],[[],46],[[],46],[[],46],[[],46],[[[51,[[0,[1,2]]]],20],[[55,[[0,[1,2]]]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[51,[[0,[1,2]]]]],[[83,[[0,[1,2]]]]]],[[51,33],84],[[[51,[[0,[1,2]]]],45],[[84,[[0,[1,2]]]]]]],"p":[[8,"Clone"],[8,"Ord"],[3,"SpkTxOutIndex"],[3,"BTreeMap"],[3,"DescriptorId"],[3,"BlockId"],[3,"ConfirmationHeightAnchor"],[3,"ConfirmationTimeHeightAnchor"],[3,"Hash"],[4,"ChainPosition"],[4,"ConfirmationTime"],[3,"FullTxOut"],[3,"SpkIterator"],[4,"Ordering"],[15,"u32"],[8,"Anchor"],[4,"Option"],[4,"Result"],[8,"Deserializer"],[15,"u64"],[8,"PartialEq"],[15,"bool"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[3,"Block"],[15,"usize"],[3,"FromSliceError"],[15,"str"],[8,"Hash"],[8,"SliceIndex"],[3,"Script"],[3,"Transaction"],[3,"OutPoint"],[3,"TxOut"],[3,"ScriptBuf"],[8,"RangeBounds"],[3,"SignedAmount"],[3,"BTreeSet"],[8,"DoubleEndedIterator"],[8,"PartialOrd"],[8,"Serializer"],[3,"String"],[8,"ExactSizeIterator"],[3,"Txid"],[3,"TypeId"],[8,"Append"],[3,"ChangeSet"],[8,"Indexer"],[3,"IndexedTxGraph"],[3,"TxGraph"],[8,"IntoIterator"],[8,"Default"],[3,"ChangeSet"],[3,"ChangeSet"],[3,"Balance"],[3,"KeychainTxOutIndex"],[4,"DescriptorPublicKey"],[4,"Descriptor"],[3,"Amount"],[3,"LocalChain"],[6,"ChangeSet"],[3,"MissingGenesisError"],[3,"Header"],[3,"CannotConnectError"],[4,"ApplyHeaderError"],[3,"CheckPoint"],[3,"AlterCheckPointError"],[3,"BlockHash"],[3,"CheckPointIter"],[3,"Demand"],[8,"Iterator"],[3,"SyncRequest"],[3,"FullScanRequest"],[8,"FnMut"],[8,"Send"],[8,"Sync"],[4,"CalculateFeeError"],[3,"TxNode"],[3,"CanonicalTx"],[3,"Arc"],[8,"Into"],[3,"TxAncestors"],[3,"TxDescendants"],[3,"HashSet"],[8,"ChainOracle"],[8,"DescriptorExt"],[8,"AnchorFromBlockPosition"],[13,"Confirmed"],[13,"Unconfirmed"],[3,"SyncResult"],[3,"FullScanResult"]]},\ "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 selects and deselects from a set of …","","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 ONLY 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 the advertised score with the current best. The …","","","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 and skip the 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.","","","The total number of inputs; so we can calculate extra …","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 …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","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"]]},\ @@ -10,6 +9,7 @@ var searchIndex = JSON.parse('{\ "bdk_persist":{"doc":"BDK Persist","t":[3,8,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,10],"n":["Persist","PersistBackend","borrow","borrow_mut","commit","fmt","from","into","load_from_persistence","new","stage","stage_and_commit","staged","try_from","try_into","type_id","vzip","write_changes"],"q":["bdk_persist","","","","","","","","","","","","","","","","",""],"d":["Persist wraps a PersistBackend to create a convenient …","A persistence backend for Persist.","","","Commit the staged changes to the underlying persistence …","","Returns the argument unchanged.","Calls U::from(self).","Return the aggregate changeset C from persistence.","Create a new Persist from PersistBackend.","Stage a changeset to be committed later with commit.","Stages a new changeset and commits it (along with any …","Get the changes that have not been committed yet.","","","","","Writes a changeset to the persistence backend."],"i":[0,0,1,1,1,1,1,1,8,1,1,1,1,1,1,1,1,8],"f":[0,0,[[]],[[]],[1,[[3,[2]]]],[[[1,[4]],5],[[7,[6]]]],[[]],[[]],[[],[[3,[2]]]],[[[0,[8,9,10]]],1],[1],[1,[[3,[2]]]],[1],[[],7],[[],7],[[],11],[[]],[[],3]],"p":[[3,"Persist"],[4,"Option"],[6,"Result"],[8,"Debug"],[3,"Formatter"],[3,"Error"],[4,"Result"],[8,"PersistBackend"],[8,"Send"],[8,"Sync"],[3,"TypeId"]]},\ "bdk_testenv":{"doc":"","t":[3,2,2,2,12,11,11,2,12,2,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11],"n":["TestEnv","anyhow","bitcoincore_rpc","bitcoind","bitcoind","borrow","borrow_mut","electrsd","electrsd","electrum_client","electrum_client","from","genesis_hash","into","invalidate_blocks","make_checkpoint_tip","mine_blocks","mine_empty_block","new","reorg","reorg_empty_blocks","reset_electrsd","rpc_client","send","try_from","try_into","type_id","vzip","wait_until_electrum_sees_block"],"q":["bdk_testenv","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Struct for running a regtest environment with a single …","","","","","","","","","","Exposes the ElectrumApi calls from the Electrum client.","Returns the argument unchanged.","Get the genesis hash of the blockchain.","Calls U::from(self).","Invalidate a number of blocks of a given size count.","Create a checkpoint linked list of all the blocks in the …","Mine a number of blocks of a given size count, which may …","Mine a block that is guaranteed to be empty even with …","Construct a new TestEnv instance with default …","Reorg a number of blocks of a given size count. Refer to …","Reorg with a number of empty blocks of a given size count.","","Exposes the RpcApi calls from bitcoincore_rpc.","Send a tx of a given amount to a given address.","","","","","This method waits for the Electrum notification indicating …"],"i":[0,0,0,0,1,1,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],"f":[0,0,0,0,0,[[]],[[]],0,0,0,[1],[[]],[1,[[3,[2]]]],[[]],[[1,4],3],[1,5],[[1,4,[7,[6]]],[[3,[[8,[2]]]]]],[1,3],[[],[[3,[1]]]],[[1,4],[[3,[[8,[2]]]]]],[[1,4],[[3,[8]]]],[1,[[3,[1]]]],[1],[[1,6,9],[[3,[10]]]],[[],11],[[],11],[[],12],[[]],[1,3]],"p":[[3,"TestEnv"],[3,"BlockHash"],[6,"Result"],[15,"usize"],[3,"CheckPoint"],[3,"Address"],[4,"Option"],[3,"Vec"],[3,"Amount"],[3,"Txid"],[4,"Result"],[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 minimum 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,"TapSighashType"],[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"]]},\ +"bdk_wallet":{"doc":"BDK Wallet","t":[13,13,2,13,4,13,3,2,2,4,2,3,11,11,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,12,12,0,14,11,11,11,11,11,11,11,11,11,11,14,11,11,11,11,11,11,11,11,11,11,12,12,0,11,12,11,0,12,11,11,11,2,2,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,12,5,11,11,11,11,0,12,12,12,13,6,4,2,4,6,8,6,8,16,4,3,13,13,2,8,4,13,13,6,13,13,13,13,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,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,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,10,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,11,11,12,11,11,11,11,11,11,11,11,11,10,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,10,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,5,5,13,13,4,13,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,3,3,8,6,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,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,13,8,4,4,4,16,16,8,4,13,8,8,3,8,13,13,13,16,4,6,13,13,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,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,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,10,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,11,11,11,11,12,12,12,11,5,11,10,11,11,5,10,11,11,12,12,11,11,11,11,11,11,10,12,11,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,11,11,8,10,10,10,3,4,3,13,3,13,13,13,13,4,8,4,13,13,13,13,13,13,4,4,13,13,13,13,13,13,13,3,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,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,0,11,12,11,11,11,11,11,11,11,11,11,11,11,11,0,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,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,12,11,12,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,0,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,0,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,5,12,12,12,12,12,12,12,12,12,12,13,13,3,13,8,3,6,4,4,13,3,13,3,11,11,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,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,12,12,12,12,12,12,12,4,13,13,13,4,13,13,13,13,13,13,13,13,4,13,13,13,13,13,13,13,13,13,13,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,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,3,6,12,11,11,11,11,11,11,11,11,11,11,11,12,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,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,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,10,11,11,11,10,11,12,11,12,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,4,4,4,13,3,13,13,4,3,13,13,13,13,13,13,3,8,4,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,11,11,11,11,11,11,11,11,11,11,11,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],"n":["External","Foreign","HdKeyPaths","Internal","KeychainKind","Local","LocalOutput","SignOptions","TxBuilder","Utxo","Wallet","WeightedUtxo","as_byte","as_ref","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","chain","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","confirmation_time","derivation_index","descriptor","descriptor","deserialize","deserialize","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fragment","from","from","from","from","hash","hash","into","into","into","into","is_spent","keychain","keys","outpoint","outpoint","partial_cmp","psbt","satisfaction_weight","sequence","serialize","serialize","signer","template","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","txout","txout","type_id","type_id","type_id","type_id","utxo","version","vzip","vzip","vzip","vzip","wallet","outpoint","psbt_input","sequence","Bare","DerivedDescriptor","Descriptor","DescriptorError","DescriptorPublicKey","ExtendedDescriptor","ExtractPolicy","HdKeyPaths","IntoWalletDescriptor","Key","Legacy","Miniscript","MultiXPub","Pkh","Policy","ScriptContext","Segwitv0","Sh","Single","TapKeyOrigins","Tr","Wpkh","Wsh","XPub","address","as_enum","as_enum","as_inner","as_node","at_derivation_index","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","branches","build_template","build_template_mall","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_pk","check_pk","check_pk","check_terminal_non_malleable","check_terminal_non_malleable","check_terminal_non_malleable","check_witness","check_witness","check_witness","checksum","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","contains_raw_pkh","derive","derived_descriptor","derived_descriptor","desc_type","descriptor_id","deserialize","deserialize","dust_value","encode","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","for_each_key","for_each_key","from","from","from","from","from","from","from","from","from","from","from_ast","from_components_unchecked","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","into","into","into","into","into_inner","into_single_descriptors","into_wallet_descriptor","into_wallet_descriptor","is_deriveable","is_multipath","is_non_malleable","iter","iter_pk","lift","lift","lift_check","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_weight","max_satisfaction_witness_elements","max_weight_to_satisfy","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","other_top_level_checks","parse","parse_descriptor","parse_insane","parse_with_ext","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pk_len","pk_len","plan","plan_mall","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","substitute_raw_pkh","template","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_into","try_into","try_into","try_into","ty","type_id","type_id","type_id","type_id","unsigned_script_sig","vzip","vzip","vzip","vzip","within_resource_limits","calc_checksum","calc_checksum_bytes","Base58","Bip32","Error","HardenedDerivationXpub","Hex","InvalidDescriptorCharacter","InvalidDescriptorChecksum","InvalidHdKeyPath","Key","Miniscript","MultiPath","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","Bip86","Bip86Public","DescriptorTemplate","DescriptorTemplateOut","P2Pkh","P2TR","P2Wpkh","P2Wpkh_P2Sh","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","build","build","build","build","build","build","build","build","build","build","build","build","build","from","from","from","from","from","from","from","from","from","from","from","from","into","into","into","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","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_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","Bip32","DerivableKey","DescriptorKey","DescriptorPublicKey","DescriptorSecretKey","Entropy","Error","ExtScriptContext","ExtendedKey","FullKey","GeneratableDefaultOptions","GeneratableKey","GeneratedKey","IntoDescriptorKey","InvalidChecksum","InvalidNetwork","InvalidScriptContext","Key","KeyError","KeyMap","Legacy","Message","Miniscript","MultiXPrv","MultiXPub","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","build_template","check_global_consensus_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_policy_validity","check_local_validity","check_pk","check_terminal_non_malleable","check_witness","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","compressed","default","deref","derive","deserialize","encode","eq","eq","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","full_derivation_paths","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_assets","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_single_keys","into_single_keys","into_xprv","into_xpub","is_deriveable","is_legacy","is_legacy","is_multipath","is_multipath","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","num_der_paths","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","serialize","sig_type","sorted_node","test_networks","to_owned","to_owned","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","AddressInfo","ApplyBlockError","Balance","CannotConnect","ChangeSet","ConfirmationHeightCannotBeGreaterThanTip","Descriptor","Descriptor","Descriptor","InsertTxError","IsDust","LoadError","LoadedDescriptorDoesNotMatch","LoadedGenesisDoesNotMatch","LoadedNetworkDoesNotMatch","MissingDescriptor","MissingGenesis","MissingNetwork","NewError","NewOrLoadError","NonEmptyDatabase","NotInitialized","NotInitialized","Persist","Persist","Persist","UnexpectedConnectedToHash","Update","Wallet","add","add_signer","address","all_unbounded_spk_iters","append","apply_block","apply_block_connected_to","apply_unconfirmed_txs","apply_update","as_ref","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","build_fee_bump","build_tx","calculate_fee","calculate_fee_rate","cancel_tx","chain","chain","checkpoints","clone","clone","clone","clone_into","clone_into","clone_into","coin_selection","commit","confirmed","default","default","default","deref","derivation_index","derivation_of_spk","descriptor_checksum","deserialize","deserialize","eq","eq","eq","error","export","finalize_psbt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","get_balance","get_descriptor_for_keychain","get_psbt_input","get_signers","get_tx","get_utxo","graph","immature","index","indexed_tx_graph","insert_checkpoint","insert_tx","insert_txout","into","into","into","into","into","into","into","into","into","into","is_dust","is_empty","is_mine","keychain","keychains","last_active_indices","latest_checkpoint","list_output","list_unspent","list_unused_addresses","load","local_chain","mark_used","network","network","new","new_no_persist","new_no_persist_with_genesis_hash","new_or_load","new_or_load_with_genesis_hash","new_with_genesis_hash","next_derivation_index","next_unused_address","peek_address","policies","provide","provide","provide","provide","provide","public_descriptor","reveal_addresses_to","reveal_next_address","secp_ctx","sent_and_received","serialize","serialize","sign","signer","spk_index","staged","start_full_scan","start_sync_with_revealed_spks","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","to_string","to_string","total","transactions","trusted_pending","trusted_spendable","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","tx_builder","tx_graph","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unbounded_spk_iter","unmark_used","untrusted_pending","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","wallet_name_from_descriptor","connected_to_hash","expected_hash","tip_height","tx_height","expected","expected","got","got","got","keychain","BnBNoExactMatch","BnBTotalTriesExceeded","BranchAndBoundCoinSelection","Change","CoinSelectionAlgorithm","CoinSelectionResult","DefaultCoinSelectionAlgorithm","Error","Excess","InsufficientFunds","LargestFirstCoinSelection","NoChange","OldestFirstCoinSelection","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","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","fmt","fmt","from","from","from","from","from","from","into","into","into","into","into","into","local_selected_amount","new","provide","selected","selected_amount","to_owned","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","available","needed","amount","change_fee","dust_threshold","fee","remaining_amount","BuildFeeBumpError","ChangePolicyDescriptor","CoinSelection","Conversion","CreateTxError","Descriptor","FeeRateTooLow","FeeRateUnavailable","FeeTooLow","InsufficientFunds","IrreplaceableTransaction","LockTime","MiniscriptPsbt","MiniscriptPsbtError","MissingKeyOrigin","MissingNonWitnessUtxo","NoRecipients","NoUtxosSelected","OutputBelowDustLimit","OutputUpdate","Persist","Policy","Psbt","RbfSequence","RbfSequenceCsv","SpendingPolicyRequired","TransactionConfirmed","TransactionNotFound","UnknownUtxo","UnknownUtxo","UtxoUpdate","Version0","Version1Csv","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","into","into","into","provide","provide","provide","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","vzip","vzip","vzip","available","csv","needed","rbf","requested","required","required","required","FullyNodedExport","WalletExport","blockheight","borrow","borrow_mut","change_descriptor","descriptor","deserialize","export_wallet","fmt","fmt","from","from_str","into","label","serialize","to_string","try_from","try_into","type_id","vzip","All","Dummy","Exclude","External","Fingerprint","Include","InputIndexOutOfRange","InputSigner","InvalidKey","InvalidNonWitnessUtxo","InvalidSighash","Legacy","MiniscriptPsbt","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_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","descriptor_secret_key","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","id","ids","into","into","into","into","into","into","into","into","new","new","partial_cmp","partial_cmp","provide","remove","remove_partial_sigs","remove_taproot_extras","sign_input","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_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","AddForeignUtxoError","AddUtxoError","AllowShrinkingError","Bip69Lexicographic","BumpFee","ChangeAllowed","ChangeForbidden","ChangeSpendPolicy","CreateTx","InvalidOutpoint","InvalidTxid","MissingScriptPubKey","MissingUtxo","OnlyChange","Shuffle","TxBuilder","TxBuilderContext","TxOrdering","UnknownUtxo","Untouched","add_data","add_foreign_utxo","add_foreign_utxo_with_sequence","add_global_xpubs","add_recipient","add_unspendable","add_utxo","add_utxos","allow_dust","allow_shrinking","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","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","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","hash","hash","include_output_redeem_witness_script","into","into","into","into","into","into","into","into","manually_selected_only","nlocktime","only_spend_change","only_witness_utxo","ordering","partial_cmp","partial_cmp","policy_path","provide","provide","provide","set_recipients","sighash","sort_tx","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_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","unspendable","version","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","foreign_utxo","input_txid"],"q":["bdk_wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::Utxo","","","bdk_wallet::descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::descriptor::checksum","","bdk_wallet::descriptor::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::descriptor::policy","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::descriptor::policy::BuildSatisfaction","","","bdk_wallet::descriptor::policy::Satisfaction","","","","","","","","","","","bdk_wallet::descriptor::policy::SatisfiableItem","","","","","","","","","","bdk_wallet::descriptor::template","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::keys","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::psbt","","","","bdk_wallet::wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::wallet::ApplyBlockError","","bdk_wallet::wallet::InsertTxError","","bdk_wallet::wallet::NewOrLoadError","","","","","","bdk_wallet::wallet::coin_selection","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::wallet::coin_selection::Error","","bdk_wallet::wallet::coin_selection::Excess","","","","","bdk_wallet::wallet::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::wallet::error::CreateTxError","","","","","","","","bdk_wallet::wallet::export","","","","","","","","","","","","","","","","","","","","","bdk_wallet::wallet::signer","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::wallet::signer::SignerContext","bdk_wallet::wallet::tx_builder","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_wallet::wallet::tx_builder::AddForeignUtxoError",""],"d":["External keychain, used for deriving recipient addresses.","A UTXO owned by another wallet.","","Internal keychain, used for deriving change addresses.","Types of keychains","A UTXO owned by the local wallet.","An unspent output owned by a Wallet.","","","An unspent transaction output (UTXO).","","A Utxo with its satisfaction_weight.","Return KeychainKind as a byte","","","","","","","","","","","","","","","","","","","","The confirmation time for transaction containing this utxo","The derivation index for the script pubkey in the wallet","Descriptors","Macro to write full descriptors with code","","","","","","","","","","","Macro to write descriptor fragments with code","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).","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 Psbt structure.","The weight of the witness data and scriptSig expressed in …","Get the sequence number if an explicit sequence number has …","","","","","","","","","","","","","","","","","Get the TxOut of the UTXO","Transaction output","","","","","The UTXO","Get the version of BDK at runtime","","","","","Wallet","The location of the output.","The information about the input we require to add it to a …","The nSequence value to set for this input.","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.","Alias for a Descriptor that can contain extended keys …","Trait implemented on Descriptors to add a method to …","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 …","Legacy ScriptContext To be used as P2SH scripts For …","The top-level miniscript abstract syntax tree (AST).","Multiple extended public keys.","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","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) …","Attempt to produce a non-malleable witness template given …","Attempt to produce a malleable witness template given the …","","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 …","Each context has slightly different rules on what Pks are …","","","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","Deprecated name for Self::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.","Add type information(Type and Extdata) to Miniscript based …","Create a new Miniscript from a Terminal node and a Type …","","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).","Extracts the AstElem representing the root of the …","Get as many descriptors as different paths in this …","Convert to wallet descriptor","","Whether or not the descriptor has any wildcards","Whether this descriptor contains a key that has multiple …","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 to conversion of a miniscript into a …","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 …","Computes an upper bound on the difference between a …","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 AST.","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 …","","","Returns a plan if the provided assets are sufficient to …","Returns a plan if the provided assets are sufficient to …","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","","","Substitutes raw public keys hashes with the public keys as …","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 miniscript can exceed the resource …","Compute the checksum of a descriptor, excludes any …","Compute the checksum bytes of a descriptor, excludes any …","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","The descriptor contains multipath keys","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}/*)","BIP86 template. Expands to tr(key/86'/{0,1}'/0'/{0,1}/*)","BIP86 public template. Expands to tr(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)","P2TR template. Expands to a descriptor tr(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.","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).","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","Multiple extended private keys.","Multiple extended public keys.","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 …","","","","","","","","","","","","","","","","","","","","","","","","","Attempt to produce a witness template given the assets …","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 …","Each context has slightly different rules on what Pks are …","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 for Self::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","Returns a vector containing the full derivation paths from …","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","Get as many keys as derivation paths in this key.","Get as many keys as derivation paths in this key.","Transform the ExtendedKey into an Xpriv for the given …","Transform the ExtendedKey into an Xpub for the given …","Whether or not the key has a wildcard","Returns whether the script context is Legacy","Returns whether the script context is …","Whether or not this key has multiple derivation paths.","Whether or not this key has multiple derivation paths.","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’…","A derived address and the index it was found at. For …","An error that may occur when applying a block to Wallet.","Balance, differentiated into various categories.","Occurs when the update chain cannot connect with original …","The changes made to a wallet by applying an Update.","The error variant that occurs when the caller attempts to …","There was problem with the passed-in descriptor(s).","There was a problem with the passed-in descriptor(s).","There is a problem with the passed-in descriptor.","An error that may occur when inserting a transaction into …","Trait to check if a value is below the dust limit. We are …","The error type when loading a Wallet from persistence.","The loaded desccriptor does not match what was provided.","The loaded genesis hash does not match what was provided.","The loaded network type does not match what was provided.","Data loaded from persistence is missing descriptor.","Data loaded from persistence is missing genesis hash.","Data loaded from persistence is missing network type.","The error type when constructing a fresh Wallet.","Error type for when we try load a Wallet from persistence …","Database already has data.","Wallet not initialized, persistence backend is empty.","Wallet is not initialized, persistence backend is empty.","We were unable to write the wallet’s data to the …","Loading data from the persistence backend failed.","Either writing to or loading from the persistence backend …","Occurs when the connected_to hash does not match the hash …","An update to Wallet.","A Bitcoin wallet","","Add an external signer","Address","Get unbounded script pubkey iterators for both Internal …","","Introduces a block of height to the wallet, and tries to …","Applies relevant transactions from block of height to the …","Apply relevant unconfirmed transactions to the wallet.","Applies an update to the wallet and stages the changes …","","","","","","","","","","","","","","","","","","","","","","Bump the fee of a transaction previously created with this …","Start building a transaction.","Calculates the fee of a given transaction. Returns 0 if tx …","Calculate the FeeRate for a given transaction.","Informs the wallet that you no longer intend to broadcast …","Update for the wallet’s internal LocalChain.","Changes to the LocalChain.","Get all the checkpoints the wallet is currently storing …","","","","","","","Coin selection","Commits all currently 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 …","","","","","","Errors that can be thrown by the Wallet","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.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Return the balance, separated into available, …","Returns the descriptor used to create addresses for a …","get the corresponding PSBT Input for a LocalUtxo","Get the signers","Get a single transaction from the wallet as a CanonicalTx …","Returns the utxo owned by this wallet corresponding to …","Update for the wallet’s internal TxGraph.","All coinbase outputs not yet matured","Child index of this address","Changes to IndexedTxGraph.","Add a new checkpoint to the wallet’s internal view of …","Add a transaction to the wallet’s internal view of the …","Inserts a TxOut at OutPoint into the wallet’s …","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).","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","Contains the last active derivation indices per keychain (K…","Returns the latest checkpoint.","List all relevant outputs (includes both spent and …","Return the list of unspent outputs of this wallet","List addresses that are revealed but unused.","Load Wallet from the given persistence backend.","Get a reference to the inner LocalChain.","Marks an address used of the given keychain at index.","Get the Bitcoin network the wallet is using.","Stores the network type of the wallet.","Initialize an empty Wallet.","Creates a wallet that does not persist data.","Creates a wallet that does not persist data, with a custom …","Either loads Wallet from persistence, or initializes it if …","Either loads Wallet from persistence, or initializes it if …","Initialize an empty Wallet with a custom genesis hash.","The index of the next address that you would get if you …","Get the next unused address for the given keychain, i.e. …","Peek an address of the given keychain at index without …","Return the spending policies for the wallet’s descriptor","","","","","","Return the “public” version of the wallet’s …","Reveal addresses up to and including the target index and …","Attempt to reveal the next address of the given keychain.","Return the secp256k1 context used for all signing …","Compute the tx’s sent and received Amounts.","","","Sign a transaction with all the wallet’s signers, in the …","Generalized signers","Get a reference to the inner KeychainTxOutIndex.","Returns the changes that will be committed with the next …","Create a `FullScanRequest for this wallet.","Create a partial SyncRequest for this wallet for all …","","","","","","","","","","","Get the whole balance visible to the wallet.","Iterate over the transactions in the wallet.","Unconfirmed UTXOs generated by a wallet tx","Get sum of trusted_pending and confirmed coins.","","","","","","","","","","","","","","","","","","","","","Transaction builder","Get a reference to the inner TxGraph.","","","","","","","","","","","Get an unbounded script pubkey iterator for the given …","Undoes the effect of mark_used and returns whether the …","Unconfirmed UTXOs received from an external wallet","","","","","","","","","","","Deterministically generate a unique name given the …","Block hash of connected_to.","Expected block hash of connected_to, as derived from block.","The internal chain’s tip height.","The introduced transaction’s confirmation height.","The expected genesis block hash.","The expected network type.","The block hash loaded from persistence.","The network type loaded from persistence.","The descriptor loaded from persistence.","The keychain of the descriptor not matching","Branch and bound coin selection tries to avoid needing a …","Branch and bound coin selection possible attempts with …","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 …","Errors that can be thrown by the coin_selection module","Remaining amount after performing coin selection","Wallet’s UTXO set is not enough to cover recipient’s …","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.","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).","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.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Sats available for spending","Sats needed for some transaction","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 …","Error returned from Wallet::build_fee_bump","The change_policy was set but the wallet does not have a …","There was an error with coin selection","Descriptor key conversion error","Error returned from TxBuilder::finish","There was a problem with the descriptors passed in","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 …","Wallet’s UTXO set is not enough to cover recipient’s …","Trying to replace a tx that has a sequence >= 0xFFFFFFFE","Requested LockTime is less than is required to spend from …","Miniscript PSBT error","Errors returned by miniscript when updating inconsistent …","In order to use the TxBuilder::add_global_xpubs option …","Missing non_witness_utxo on foreign utxo for given OutPoint","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","Return error type for …","We were unable to load wallet data from or write wallet …","There was a problem while extracting and manipulating …","Partially signed bitcoin transaction error","Cannot enable RBF with a Sequence >= 0xFFFFFFFE","Cannot enable RBF with Sequence given a required OP_CSV","Spending policy is not compatible with this KeychainKind","Happens when trying to bump a transaction that is already …","Thrown when a tx is not found in the internal database","Happens when trying to spend an UTXO that is not in the …","Happens when trying to spend an UTXO that is not in the …","Return error type for PsbtExt::update_input_with_descriptor","Requested invalid transaction version ‘0’","Requested transaction version 1, but at least 2 is needed …","","","","","","","","","","","","","","","Returns the argument unchanged.","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","","Sats available for spending","Required OP_CSV Sequence","Sats needed for some transaction","Given RBF Sequence","Requested LockTime","Required LockTime","Required fee absolute value (satoshi)","Required fee rate","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.","To be used only by external libraries implementing …","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","Miniscript PSBT error","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 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 …","Whether to remove taproot specific fields from the PSBT on …","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","Error returned from TxBuilder::add_foreign_utxo.","Error returned from TxBuilder::add_utxo and …","Error returned from TxBuilder::allow_shrinking","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 …","Requested outpoint doesn’t exist in the tx (vout greater …","Foreign utxo outpoint txid does not match PSBT input txid","Script/PubKey was not in the original transaction","Foreign utxo missing witness_utxo or non_witness_utxo","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","Happens when trying to spend an UTXO that is not in the …","Unchanged","Add data as an output, using OP_RETURN","Add a foreign UTXO i.e. a UTXO not owned by this wallet.","Same as add_foreign_utxo but allows to set the nSequence …","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 The fee_absolute method refers to the …","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.","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).","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","","","","","","","","","Foreign UTXO outpoint","PSBT input txid"],"i":[1,5,0,1,0,5,0,0,0,0,0,0,1,1,1,3,4,5,1,3,4,5,0,1,3,4,5,1,3,4,5,1,3,3,0,0,1,3,1,3,4,5,1,3,4,5,0,1,3,4,5,1,3,1,3,4,5,3,3,0,5,3,1,0,4,5,1,3,0,0,1,3,4,5,1,3,4,5,1,3,4,5,5,3,1,3,4,5,4,0,1,3,4,5,0,209,209,209,17,0,0,0,0,0,0,0,0,49,0,0,26,17,0,0,0,17,26,0,17,17,17,26,17,35,36,23,23,17,17,35,36,23,17,35,36,23,23,23,23,0,49,35,36,49,36,49,49,35,36,49,35,36,49,49,35,36,49,35,36,49,35,36,0,17,35,36,23,17,35,36,23,17,35,36,23,23,17,17,17,17,17,17,23,17,23,17,35,36,23,0,17,23,23,210,17,23,17,17,17,35,36,23,23,17,23,17,17,17,17,17,17,17,35,36,23,23,23,17,23,23,23,17,23,23,23,17,17,23,23,17,17,35,36,23,17,35,36,23,23,17,175,63,17,17,23,23,23,17,23,23,49,35,36,23,17,23,17,49,35,36,17,17,17,17,17,17,17,17,17,17,17,17,17,17,23,49,23,17,23,23,17,35,36,23,49,35,36,17,17,0,23,17,23,17,23,23,17,17,23,17,23,49,35,36,23,0,17,35,36,23,17,23,17,49,49,17,23,17,35,36,23,17,35,36,23,23,17,35,36,23,17,17,35,36,23,23,0,0,48,48,0,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,84,77,77,0,85,0,0,84,83,0,84,84,77,77,77,84,85,46,77,85,85,0,0,0,46,46,83,84,84,0,0,84,84,84,83,83,84,85,47,86,77,46,83,84,85,47,86,77,46,83,84,85,47,86,46,83,84,85,47,86,46,47,86,86,83,84,85,47,86,77,83,84,85,47,86,77,77,46,83,84,85,85,47,47,86,77,46,47,83,86,84,47,83,84,85,47,86,77,46,84,85,86,47,86,77,47,47,83,84,85,47,86,86,83,84,85,47,86,46,77,83,84,85,47,86,77,46,83,84,85,47,86,77,46,83,84,85,47,86,77,46,83,84,85,47,86,77,46,211,211,211,212,213,214,213,214,213,214,213,214,213,214,215,216,217,218,219,220,220,219,221,222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,223,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,87,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,89,90,91,93,95,96,97,98,99,100,101,102,78,0,0,0,0,224,224,0,0,111,0,0,0,0,78,78,78,49,0,0,22,78,78,108,26,224,115,0,115,0,0,22,26,108,0,0,0,0,22,0,111,108,26,0,225,26,115,106,113,22,107,78,104,26,108,109,110,111,115,106,113,22,107,78,104,26,108,109,110,111,104,49,49,49,49,49,49,49,49,49,106,22,107,104,26,108,109,110,111,106,22,107,104,26,108,109,110,111,104,26,109,111,107,107,106,26,26,104,22,104,26,108,109,110,111,113,22,107,78,78,104,104,26,26,108,108,109,110,111,104,115,115,115,106,113,22,107,78,78,78,104,26,26,108,109,110,111,113,113,26,108,104,26,26,224,226,224,226,115,26,104,26,109,111,115,106,113,22,107,78,104,26,108,109,110,111,26,88,94,106,106,113,26,108,94,115,106,106,26,108,115,115,26,225,22,26,108,225,22,225,22,26,26,104,109,110,104,0,26,49,104,104,0,49,104,26,109,110,49,113,104,26,109,111,49,104,78,104,104,104,26,49,104,0,106,22,107,104,26,108,109,110,111,108,78,104,26,108,49,49,104,115,106,113,22,107,78,104,26,108,109,110,111,115,106,113,22,107,78,104,26,108,109,110,111,115,106,113,22,107,78,104,26,108,109,110,111,115,106,113,22,107,78,104,26,108,109,110,111,0,227,227,227,0,0,0,156,0,155,152,153,154,0,0,0,154,154,154,153,153,153,0,0,152,153,154,152,153,154,156,0,0,123,124,148,124,129,124,124,124,124,124,123,124,135,129,148,152,153,154,155,156,123,124,135,129,148,152,153,154,155,156,124,124,124,124,124,135,129,124,123,135,129,123,135,129,0,124,123,123,135,129,148,124,124,124,123,129,123,129,148,0,0,124,123,123,124,135,129,148,148,152,152,153,153,154,154,155,155,156,156,123,124,135,135,135,129,129,129,148,152,153,154,155,156,124,124,124,124,124,124,135,123,148,129,124,124,124,123,124,135,129,148,152,153,154,155,156,228,129,124,148,124,135,124,124,124,124,124,124,124,124,129,124,124,124,124,124,124,124,124,124,124,152,153,154,155,156,124,124,124,124,124,123,129,124,0,124,124,124,124,123,135,129,123,148,152,153,154,155,156,123,124,123,123,123,124,135,129,148,152,153,154,155,156,123,124,135,129,148,152,153,154,155,156,0,124,123,124,135,129,148,152,153,154,155,156,124,124,123,123,124,135,129,148,152,153,154,155,156,0,229,229,230,230,231,232,231,232,233,233,185,185,0,186,0,0,0,0,0,185,0,186,0,185,186,184,181,182,183,185,186,184,181,182,183,181,182,183,181,182,183,201,181,182,183,0,181,182,183,184,184,185,185,186,184,181,182,183,185,186,184,181,182,183,185,186,184,181,182,183,184,183,185,184,184,181,182,183,185,185,186,184,181,182,183,185,186,184,181,182,183,185,186,184,181,182,183,185,186,184,181,182,183,234,234,235,236,236,235,236,0,165,165,187,0,165,165,142,165,165,142,165,165,0,165,165,165,165,165,187,165,165,165,165,165,165,142,142,165,142,187,165,165,187,165,142,187,165,142,187,187,187,187,165,165,142,142,187,165,165,165,165,165,165,142,187,165,142,187,165,142,187,187,165,142,187,165,142,187,165,142,187,165,142,187,165,142,237,238,237,238,239,239,240,241,0,0,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,189,195,190,195,151,190,195,151,0,151,151,151,192,151,151,151,151,151,151,151,195,190,192,151,0,0,0,0,0,0,0,0,192,0,0,151,45,150,150,45,150,190,151,192,194,125,45,150,195,190,151,192,194,125,45,150,195,45,190,192,194,125,45,150,195,190,192,194,125,45,150,195,190,125,125,45,150,195,194,242,194,194,194,190,192,125,195,45,190,151,151,192,194,125,45,150,195,190,190,190,151,151,192,194,125,45,150,195,190,242,194,194,194,45,190,151,192,194,125,45,150,195,194,45,190,125,151,45,150,150,243,194,194,194,126,194,150,45,150,190,192,194,125,45,150,195,151,150,150,190,151,192,194,125,45,150,195,190,151,192,194,125,45,150,195,190,151,192,194,125,45,150,195,190,151,192,194,125,45,150,195,244,0,0,0,206,0,205,205,0,0,202,202,204,202,205,206,0,0,0,203,206,141,141,141,141,141,141,141,141,141,141,143,140,141,203,202,204,206,205,143,140,141,203,202,204,206,205,141,143,140,141,206,205,143,140,141,206,205,206,205,141,141,143,140,206,205,141,141,141,141,141,206,205,141,141,141,143,140,141,203,203,202,202,204,204,206,205,143,140,141,203,202,204,206,205,206,205,141,143,140,141,203,202,204,206,205,141,141,141,141,141,206,205,141,203,202,204,141,141,206,143,140,141,206,205,203,202,204,143,140,141,203,202,204,206,205,143,140,141,203,202,204,206,205,143,140,141,203,202,204,206,205,141,141,143,140,141,203,202,204,206,205,245,245],"f":[0,0,0,0,0,0,0,0,0,0,0,0,[1,2],[1],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[1,1],[3,3],[4,4],[5,5],[[]],[[]],[[]],[[]],[[1,1],6],0,0,0,0,[[],[[7,[1]]]],[[],[[7,[3]]]],[[1,1],8],[[3,3],8],[[4,4],8],[[5,5],8],[[1,9],10],[[3,9],10],[[4,9],10],[[5,9],10],0,[[]],[[]],[[]],[[]],[1],[3],[[]],[[]],[[]],[[]],0,0,0,[5,11],0,[[1,1],[[12,[6]]]],0,0,[5,[[12,[13]]]],[1,7],[3,7],0,0,[[]],[[]],[[]],[[]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[5,14],0,[[],15],[[],15],[[],15],[[],15],0,[[],16],[[]],[[]],[[]],[[]],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,[[17,18],[[7,[[20,[19]],21]]]],[[],22],[[],22],[23,24],[23,[[25,[23]]]],[[[17,[26]],27],[[7,[[17,[28]],29]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[23,[[31,[23,30]]]],[23,[[33,[32]]]],[23,[[33,[32]]]],0,[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[24,[[7,[34]]]],[24,[[7,[34]]]],[24,[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],0,[17,17],[35,35],[36,36],[23,23],[[]],[[]],[[]],[[]],[[17,17],6],[[35,35],6],[[36,36],6],[[23,23],6],[23,8],[[[17,[26]],27],[[7,[[17,[28]],29]]]],[[[17,[26]],37,27],[[7,[[17,[38]],29]]]],[[[17,[28]],37],[[7,[[17,[38]],29]]]],[17,39],[[[17,[26]]],40],[[],[[7,[17]]]],[[],[[7,[23]]]],[[[17,[26]]],41],[23,42],[[17,17],8],[[35,35],8],[[36,36],8],[[23,23],8],0,[17,[[7,[42,21]]]],0,[[23,43],[[7,[44]]]],[[45,46,37],[[7,[[12,[47]],48]]]],[[[17,[26]],45,46,37],[[7,[[12,[47]],48]]]],[[[23,[26,49]],45,46,37],[[7,[[12,[47]],48]]]],[[[17,[26]],37,50,[51,[27]]],[[7,[12,29]]]],[[17,9],[[7,[52]]]],[[17,9],[[7,[52]]]],[[35,9],[[7,[52]]]],[[36,9],[[7,[52]]]],[[23,9],[[7,[52]]]],[[23,9],[[7,[52]]]],[17,8],[23,8],[[]],[53,17],[54,17],[55,17],[56,17],[57,17],[58,17],[[]],[[]],[[]],[24,[[7,[23,21]]]],[[24,59,60],23],[16,[[7,[17,21]]]],[16,[[7,[23,21]]]],[[16,43],[[7,[23,21]]]],[16,[[7,[23,21]]]],[61,[[7,[17,21]]]],[61,[[7,[23,21]]]],[[23,62],[[12,[23]]]],[[23,62],12],[17,[[7,[21]]]],[17,[[7,[21]]]],[23,8],[23,8],[[[17,[26]]],8],[17],[35],[36],[23],[[]],[[]],[[]],[[]],[23,24],[[[17,[26]]],[[7,[[31,[[17,[26]],30]],21]]]],[[37,18],[[7,[48]]]],[[63,37,18],[[7,[48]]]],[[[17,[26]]],8],[[[17,[26]]],8],[23,8],[23,64],[23,65],[17,[[7,[66,21]]]],[23,[[7,[66,21]]]],[23,[[7,[67]]]],[23,[[12,[62]]]],[23,[[12,[62]]]],[23,[[12,[62]]]],[23,[[7,[62,21]]]],[17,[[7,[62,21]]]],[23,[[7,[62,21]]]],[17,[[7,[62,21]]]],[[],16],[[],16],[[],16],[[[23,[68]]],[[7,[17,21]]]],[[],17],[[],[[7,[17,21]]]],[[[23,[35]]],[[7,[17,21]]]],[[62,[31,[30]]],[[7,[17,21]]]],[58,17],[55,17],[[],[[7,[17,21]]]],[[[23,[36]]],[[7,[17,21]]]],[[62,[31,[30]]],[[7,[17,21]]]],[[[12,[69]]],[[7,[17,21]]]],[[],[[7,[17,21]]]],[[[23,[36]]],[[7,[17,21]]]],[[62,[31,[30]]],[[7,[17,21]]]],0,[23,[[7,[21]]]],[50,[[7,[23,21]]]],[[37,16],[[7,[21]]]],[50,[[7,[23,21]]]],[[50,43],[[7,[23,21]]]],[[17,17],[[12,[6]]]],[[35,35],[[12,[6]]]],[[36,36],[[12,[6]]]],[[23,23],[[12,[6]]]],[[],62],[[],62],[[],62],[[[17,[28]]],[[7,[70,[17,[28]]]]]],[[[17,[28]]],[[7,[70,[17,[28]]]]]],0,[23,8],[17,[[7,[21]]]],[23,[[7,[44]]]],[[17,71],[[7,[21]]]],[23,[[7,[[31,[[31,[2,30]],30]],21]]]],[23,[[7,[[31,[[31,[2,30]],30]],21]]]],[17,[[7,[42,21]]]],[17,42],[23,62],[17,7],[23,7],[[],72],[[],72],[[],72],[[23,73],23],0,[[]],[[]],[[]],[[]],[[],74],[[],74],[[[17,[26]],73],74],[23,[[7,[21]]]],[23,[[7,[21]]]],[17,[[7,[75]]]],[23,[[7,[75]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],0,[[],15],[[],15],[[],15],[[],15],[17,42],[[]],[[]],[[]],[[]],[23,8],[16,[[7,[74,48]]]],[16,[[7,[48]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[48,9],10],[[48,9],10],[76,48],[77,48],[78,48],[[]],[21,48],[79,48],[80,48],[81,48],[[]],[82],[[],74],[[],7],[[],7],[[],15],[[]],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,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[83,83],[84,84],[85,85],[47,47],[86,86],[46,46],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[],86],[[83,83],8],[[84,84],8],[[85,85],8],[[47,47],8],[[86,86],8],[[77,77],8],[[83,9],10],[[84,9],10],[[85,9],10],[[47,9],10],[[86,9],10],[[77,9],10],[[77,9],10],[[46,9],10],[[]],[[]],[[]],[8,85],[[]],[84,47],[[]],[[]],[[]],[[47,73],[[7,[86,77]]]],[83],[86],[84,74],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[84,8],[85,8],[86,8],0,[[86,86],[[12,[6]]]],[82],[47,8],0,[83,7],[84,7],[85,7],[47,7],[86,7],0,[[]],[[]],[[]],[[]],[[]],[[]],[[],74],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],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,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[18,[[7,[87,48]]]],[[[89,[[88,[35]]]],18],[[7,[87,48]]]],[[[90,[[88,[36]]]],18],[[7,[87,48]]]],[[[91,[[88,[36]]]],18],[[7,[87,48]]]],[[[93,[[88,[92]]]],18],[[7,[87,48]]]],[[[95,[[94,[35]]]],18],[[7,[87,48]]]],[[[96,[[94,[35]]]],18],[[7,[87,48]]]],[[[97,[[94,[36]]]],18],[[7,[87,48]]]],[[[98,[[94,[36]]]],18],[[7,[87,48]]]],[[[99,[[94,[36]]]],18],[[7,[87,48]]]],[[[100,[[94,[36]]]],18],[[7,[87,48]]]],[[[101,[[94,[92]]]],18],[[7,[87,48]]]],[[[102,[[94,[92]]]],18],[[7,[87,48]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[87,37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[37,18],[[7,[48]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],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,[[],103],[[],22],[[26,27],[[7,[28,29]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[104,[[33,[32]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[[],[[7,[34]]]],[24,[[7,[34]]]],[[],[[7,[34]]]],[[[106,[105,49]]],[[106,[105,49]]]],[22,22],[107,107],[104,104],[26,26],[108,108],[109,109],[110,110],[111,111],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[104,104],6],[[26,26],6],[[109,109],6],[[111,111],6],0,[[],107],[[[106,[49]]]],[[26,27],[[7,[28,29]]]],[[],[[7,[26]]]],[104,42],[[22,22],8],[[104,104],8],[[26,26],8],[[108,108],8],[[109,109],8],[[110,110],8],[[111,111],8],[[[113,[[0,[112,49]]]],9],10],[[22,9],10],[[107,9],10],[[78,9],10],[[78,9],10],[[104,9],[[7,[52]]]],[[104,9],[[7,[52]]]],[[26,9],[[7,[52]]]],[[26,9],[[7,[52]]]],[[108,9],[[7,[52]]]],[[108,9],[[7,[52]]]],[[109,9],[[7,[52]]]],[[110,9],[[7,[52]]]],[[111,9],[[7,[52]]]],[104,8],[[]],[114,[[115,[49]]]],[116,[[115,[49]]]],[[]],[[]],[[]],[[]],[[]],[21,78],[81,78],[[]],[28,26],[[]],[[]],[[]],[[]],[[]],[[26,103],[[113,[49]]]],[[108,103],[[113,[49]]]],[16,[[7,[26]]]],[16,[[7,[108]]]],[61,[[7,[104,21]]]],[26,[[12,[117]]]],[26,[[31,[117,30]]]],[[],[[7,[106]]]],[[],[[7,[106]]]],[[],[[7,[106]]]],[[],[[7,[106]]]],[[[115,[49]]],8],[26,8],[104],[26],[109],[111],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[26,118],[[],[[7,[113,78]]]],[[[12,[119]],117],[[7,[113,78]]]],[[106,[12,[119]],117],[[7,[113,78]]]],[106,[[7,[113,78]]]],[[[113,[49]]],[[7,[[113,[49]],78]]]],[26,[[7,[[113,[49]],78]]]],[108,[[7,[[113,[49]],78]]]],[[],[[7,[115,78]]]],[[[115,[49]]],[[7,[[115,[49]],78]]]],[106,[[7,[115,78]]]],[[[106,[49]]]],[26,[[31,[26,30]]]],[108,[[31,[108,30]]]],[[[115,[49]],18],[[12,[116]]]],[[[115,[49]],18,37],114],[26,8],[[],8],[22,8],[26,8],[108,8],[[],8],[22,8],[[],8],[22,8],[26,8],[26,8],0,0,0,[104,[[7,[66,21]]]],[[],103],[26,120],[23,[[12,[62]]]],[104,62],[104,62],[[103,103],103],[[],16],[[62,[31,[30]]],[[7,[104,21]]]],[26,62],0,0,[23,[[7,[21]]]],[[[113,[49]],103],[[113,[49]]]],[[104,104],[[12,[6]]]],[[26,26],[[12,[6]]]],[[109,109],[[12,[6]]]],[[111,111],[[12,[6]]]],[[],62],0,[82],[104,[[7,[21]]]],[104,[[7,[[31,[[31,[2,30]],30]],21]]]],[104,62],[26,7],[[],72],[104,24],[[],103],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[108,37],[[7,[26,121]]]],[[],74],[[],74],[[],74],[[],74],[23,[[7,[21]]]],[23,[[7,[21]]]],[104,[[7,[104,75]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],[[12,[41]]]],[[],[[12,[122]]]],[62,[[12,[14]]]],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,[[123,123],123],[[124,1,125,[127,[126]]]],0,[124,[[73,[1,[0,[128,105]]]]]],[[129,129]],[[124,130,27],[[7,[131]]]],[[124,130,27,132],[[7,[133]]]],[[124,134]],[[124,[136,[135]]],[[7,[131]]]],[124,137],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[124,138],[[7,[[141,[139,140]],142]]]],[124,[[141,[139,143]]]],[[124,144],[[7,[41,145]]]],[[124,144],[[7,[122,145]]]],[[124,144]],0,0,[124,146],[123,123],[135,135],[129,129],[[]],[[]],[[]],0,[124,[[147,[8]]]],0,[[],123],[[],135],[[],129],[148],[[124,1],[[12,[27]]]],[[124,50],12],[[124,1],74],[[],[[7,[123]]]],[[],[[7,[129]]]],[[123,123],8],[[129,129],8],[[148,148],8],0,0,[[124,149,150],[[7,[8,151]]]],[[123,9],[[7,[52]]]],[[123,9],[[7,[52]]]],[[124,9],10],[[135,9],10],[[129,9],10],[[148,9],10],[[148,9],10],[[152,9],10],[[152,9],10],[[153,9],10],[[153,9],10],[[154,9],10],[[154,9],10],[[155,9],10],[[155,9],10],[[156,9],10],[[156,9],10],[[]],[[]],[[[157,[1]]],135],[158,135],[[]],[[[161,[159,[160,[1]]]]],129],[162,129],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[124,123],[[124,1],63],[[124,3,[12,[163]],8],[[7,[164,165]]]],[[124,1],[[127,[45]]]],[[124,138],[[12,[[166,[[127,[144]],159]]]]]],[[124,11],[[12,[3]]]],0,0,0,0,[[124,132],[[7,[8,167]]]],[[124,144,168],[[7,[8,155]]]],[[124,11,14]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[50,8],[129,8],[[124,50],8],0,[124,128],0,[124,169],[124,128],[124,128],[[124,1],170],[[[0,[[171,[129]],172,173]]],[[7,[124,153]]]],[124,174],[[124,1,27],8],[124,18],0,[[175,[12,[175]],[0,[[171,[129]],172,173]],18],[[7,[124,152]]]],[[175,[12,[175]],18],[[7,[124,48]]]],[[175,[12,[175]],18,176],[[7,[124,48]]]],[[175,[12,[175]],[0,[[171,[129]],172,173]],18],[[7,[124,154]]]],[[175,[12,[175]],[0,[[171,[129]],172,173]],18,176],[[7,[124,154]]]],[[175,[12,[175]],[0,[[171,[129]],172,173]],18,176],[[7,[124,152]]]],[[124,1],27],[[124,1],[[147,[148]]]],[[124,1,27],148],[[124,1],[[7,[[12,[47]],48]]]],[82],[82],[82],[82],[82],[[124,1],[[12,[63]]]],[[124,1,27],[[147,[128]]]],[[124,1],[[147,[148]]]],[124,37],[[124,144]],[123,7],[129,7],[[124,149,150],[[7,[8,151]]]],0,[124,177],[124,129],[124,[[178,[1]]]],[124,179],[[]],[[]],[[]],[[],74],[[],74],[[],74],[[],74],[[],74],[[],74],[[],74],[123,180],[124,128],0,[123,180],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],0,[124,137],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[124,1],[[0,[128,105]]]],[[124,1,27],8],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[12,18,37],[[7,[74,48]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[181,181],[182,182],[183,183],[[]],[[]],[[]],[[[31,[4]],[31,[4]],122,41,50],[[7,[184,185]]]],[[181,[31,[4]],[31,[4]],122,41,50],[[7,[184,185]]]],[[182,[31,[4]],[31,[4]],122,41,50],[[7,[184,185]]]],[[183,[31,[4]],[31,[4]],122,41,50],[[7,[184,185]]]],[[41,122,50],186],[[],181],[[],182],[[],183],0,0,[[185,9],10],[[185,9],10],[[186,9],10],[[184,9],10],[[181,9],10],[[182,9],10],[[183,9],10],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[184,41],[41,183],[82],0,[184,41],[[]],[[]],[[]],[[],74],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],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,[[]],[[]],[[]],[[]],[[]],[[]],[187,187],[[]],[[187,9],10],[[187,9],10],[[165,9],10],[[165,9],10],[[142,9],10],[[142,9],10],[[]],[187,165],[48,165],[77,165],[188,165],[[]],[185,165],[[]],[[]],[[]],[[]],[82],[82],[82],[[]],[[],74],[[],74],[[],74],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[189,[[12,[74]]]],[189,74],[[],[[7,[189]]]],[[124,16,8],[[7,[189,16]]]],[[189,9],10],[[189,9],10],[[]],[16,[[7,[189]]]],[[]],0,[189,7],[[],74],[[],7],[[],7],[[],15],[[]],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,[[45,190,125,[127,[126]]],[[12,[[127,[126]]]]]],0,0,[[45,37],191],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[191,17,37],45],[190,190],[192,192],[[[194,[[0,[105,193,112,105]]]]],[[194,[[0,[105,193,112,105]]]]]],[125,125],[45,45],[150,150],[195,195],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[190,190],6],[[125,125],6],[[],125],[[],45],[[],150],[[],195],[[[194,[[0,[193,112,105]]]]]],[[],[[12,[108]]]],[[[194,[196]]],[[12,[108]]]],[[[194,[[197,[116]]]]],[[12,[108]]]],[[[194,[[198,[116]]]]],[[12,[108]]]],[[190,190],8],[[192,192],8],[[125,125],8],[[195,195],8],[[45,190],[[12,[127]]]],[[190,9],10],[[151,9],10],[[151,9],10],[[192,9],10],[[[194,[[0,[112,193,112,105]]]],9],10],[[125,9],10],[[45,9],10],[[150,9],10],[[195,9],10],[[]],[199,190],[120,190],[[]],[200,151],[[]],[[]],[[]],[[]],[[]],[[]],[190],[37,190],[[[194,[196]],37],190],[[[194,[[198,[116]]]],37],190],[[[194,[[197,[116]]]],37],190],[45,[[31,[190]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[0,[193,112,105]],192],[[194,[[0,[193,112,105]]]]]],[[],45],[[190,190],[[12,[6]]]],[[125,125],[[12,[6]]]],[82],[[45,190,125],[[12,[[127,[126]]]]]],0,0,[[149,62,150,37],[[7,[151]]]],[[[194,[[198,[116]]]],149,62,150,37],[[7,[151]]]],[[[194,[196]],149,62,150,37],[[7,[151]]]],[[[194,[[197,[116]]]],149,62,150,37],[[7,[151]]]],[[149,150,37],[[7,[151]]]],[[149,150,37],[[7,[151]]]],0,[45,[[31,[127]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],74],0,0,[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[[141,[201,143]]],[[141,[201,143]]]],[[141,11,164,62],[[7,[141,202]]]],[[141,11,164,62,13],[[7,[141,202]]]],[141,141],[[[141,[201,143]],42,180],[[141,[201,143]]]],[[141,11],141],[[141,11],[[7,[141,203]]]],[141,[[7,[141,203]]]],[[141,8],141],[[[141,[139,140]],42],[[7,[[141,[139,140]],204]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[141,205],141],[143,143],[140,140],[[[141,[105]]],[[141,[105]]]],[206,206],[205,205],[[]],[[]],[[]],[[]],[[]],[[206,206],6],[[205,205],6],[[141,201],[[141,[201]]]],[[141,27],141],[[],143],[[],140],[[],206],[[],205],[141,141],[[[141,[201,143]],42],[[141,[201,143]]]],[141,141],[141,141],[[141,13],141],[[206,206],8],[[205,205],8],[[141,41],141],[[141,122],141],[[[141,[201]]],[[7,[149,165]]]],[[143,9],10],[[140,9],10],[[[141,[112,112]],9],10],[[203,9],10],[[203,9],10],[[202,9],10],[[202,9],10],[[204,9],10],[[204,9],10],[[206,9],10],[[205,9],10],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[206],[205],[141,141],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[141,141],[[141,207],141],[141,141],[141,141],[[141,206],141],[[206,206],[[12,[6]]]],[[205,205],[[12,[6]]]],[[141,[73,[74,[31,[62]]]],1],141],[82],[82],[82],[[[141,[201,143]],31],[[141,[201,143]]]],[[141,163],141],[[206,144]],[[]],[[]],[[]],[[]],[[]],[[],74],[[],74],[[],74],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[141,[31,[11]]],141],[[141,208],141],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0],"p":[[4,"KeychainKind"],[15,"u8"],[3,"LocalOutput"],[3,"WeightedUtxo"],[4,"Utxo"],[4,"Ordering"],[4,"Result"],[15,"bool"],[3,"Formatter"],[6,"Result"],[3,"OutPoint"],[4,"Option"],[3,"Sequence"],[3,"TxOut"],[3,"TypeId"],[15,"str"],[4,"Descriptor"],[4,"Network"],[4,"NetworkChecked"],[3,"Address"],[4,"Error"],[4,"ScriptContextEnum"],[3,"Miniscript"],[4,"Terminal"],[4,"Tree"],[4,"DescriptorPublicKey"],[15,"u32"],[3,"DefiniteDescriptorKey"],[4,"ConversionError"],[3,"Global"],[3,"Vec"],[4,"Placeholder"],[3,"Satisfaction"],[4,"ScriptContextError"],[4,"Legacy"],[4,"Segwitv0"],[3,"Secp256k1"],[3,"PublicKey"],[4,"DescriptorType"],[3,"DescriptorId"],[15,"u64"],[3,"ScriptBuf"],[3,"ExtParams"],[4,"AnalysisError"],[3,"SignersContainer"],[4,"BuildSatisfaction"],[3,"Policy"],[4,"Error"],[8,"ScriptContext"],[3,"Script"],[3,"Range"],[3,"Error"],[3,"Pkh"],[3,"Bare"],[3,"Wsh"],[3,"Sh"],[3,"Tr"],[3,"Wpkh"],[3,"Type"],[3,"ExtData"],[3,"Tree"],[15,"usize"],[6,"ExtendedDescriptor"],[3,"Iter"],[3,"PkIter"],[4,"Policy"],[4,"LiftError"],[4,"BareCtx"],[4,"TapTree"],[3,"Plan"],[3,"TxIn"],[4,"SigType"],[3,"BTreeMap"],[3,"String"],[4,"TranslateErr"],[4,"HexToBytesError"],[4,"PolicyError"],[4,"KeyError"],[4,"Error"],[4,"Error"],[4,"Error"],[3,"Demand"],[4,"PkOrF"],[4,"SatisfiableItem"],[4,"Satisfaction"],[3,"Condition"],[6,"DescriptorTemplateOut"],[8,"IntoDescriptorKey"],[3,"P2Pkh"],[3,"P2Wpkh_P2Sh"],[3,"P2Wpkh"],[4,"Tap"],[3,"P2TR"],[8,"DerivableKey"],[3,"Bip44"],[3,"Bip44Public"],[3,"Bip49"],[3,"Bip49Public"],[3,"Bip84"],[3,"Bip84Public"],[3,"Bip86"],[3,"Bip86Public"],[6,"ValidNetworks"],[3,"SortedMultiVec"],[8,"Clone"],[3,"GeneratedKey"],[3,"PrivateKeyGenerateOptions"],[4,"DescriptorSecretKey"],[3,"SinglePub"],[3,"SinglePriv"],[4,"SinglePubKey"],[8,"Debug"],[4,"DescriptorKey"],[3,"Xpub"],[4,"ExtendedKey"],[3,"Xpriv"],[3,"DerivationPath"],[3,"Assets"],[6,"KeySource"],[3,"Fingerprint"],[3,"DescriptorKeyParseError"],[3,"FeeRate"],[3,"Balance"],[3,"Wallet"],[3,"SignerOrdering"],[8,"TransactionSigner"],[3,"Arc"],[8,"Iterator"],[3,"ChangeSet"],[3,"Block"],[3,"CannotConnectError"],[3,"BlockId"],[4,"ApplyHeaderError"],[8,"IntoIterator"],[3,"Update"],[8,"Into"],[3,"TxGraph"],[3,"Txid"],[6,"DefaultCoinSelectionAlgorithm"],[3,"BumpFee"],[3,"TxBuilder"],[4,"BuildFeeBumpError"],[3,"CreateTx"],[3,"Transaction"],[4,"CalculateFeeError"],[3,"CheckPointIter"],[6,"Result"],[3,"AddressInfo"],[3,"Psbt"],[3,"SignOptions"],[4,"SignerError"],[4,"NewError"],[4,"LoadError"],[4,"NewOrLoadError"],[4,"InsertTxError"],[4,"ApplyBlockError"],[3,"FullScanResult"],[3,"SyncResult"],[3,"ConfirmationTimeHeightAnchor"],[3,"ChangeSet"],[3,"ChangeSet"],[6,"ChangeSet"],[3,"PsbtSighashType"],[3,"Input"],[4,"CreateTxError"],[3,"CanonicalTx"],[3,"AlterCheckPointError"],[4,"ConfirmationTime"],[3,"CheckPoint"],[8,"DoubleEndedIterator"],[8,"PersistBackend"],[8,"Send"],[8,"Sync"],[3,"LocalChain"],[8,"IntoWalletDescriptor"],[3,"BlockHash"],[3,"KeychainTxOutIndex"],[3,"FullScanRequest"],[3,"SyncRequest"],[3,"Amount"],[3,"LargestFirstCoinSelection"],[3,"OldestFirstCoinSelection"],[3,"BranchAndBoundCoinSelection"],[3,"CoinSelectionResult"],[4,"Error"],[4,"Excess"],[4,"MiniscriptPsbtError"],[4,"Error"],[3,"FullyNodedExport"],[4,"SignerId"],[6,"KeyMap"],[4,"SignerContext"],[8,"Sized"],[3,"SignerWrapper"],[4,"TapLeavesOptions"],[3,"PrivateKey"],[3,"DescriptorXKey"],[3,"DescriptorMultiXKey"],[3,"Hash"],[4,"Error"],[8,"CoinSelectionAlgorithm"],[4,"AddForeignUtxoError"],[4,"AddUtxoError"],[4,"AllowShrinkingError"],[4,"ChangeSpendPolicy"],[4,"TxOrdering"],[4,"LockTime"],[15,"i32"],[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,"UnexpectedConnectedToHash"],[13,"ConfirmationHeightCannotBeGreaterThanTip"],[13,"LoadedGenesisDoesNotMatch"],[13,"LoadedNetworkDoesNotMatch"],[13,"LoadedDescriptorDoesNotMatch"],[13,"InsufficientFunds"],[13,"Change"],[13,"NoChange"],[13,"InsufficientFunds"],[13,"RbfSequenceCsv"],[13,"LockTime"],[13,"FeeTooLow"],[13,"FeeRateTooLow"],[8,"SignerCommon"],[8,"InputSigner"],[13,"Tap"],[13,"InvalidTxid"]]},\ "example_bitcoind_rpc_polling":{"doc":"","t":[13,17,6,17,17,17,4,13,17,13,3,4,17,13,13,11,11,11,11,5,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,5,11,12,12,12,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,12,12],"n":["Block","CHANNEL_BOUND","ChangeSet","DB_COMMIT_DELAY","DB_MAGIC","DB_PATH","Emission","Live","MEMPOOL_EMIT_DELAY","Mempool","RpcArgs","RpcCommands","STDOUT_PRINT_DELAY","Sync","Tip","augment_args","augment_args_for_update","augment_subcommands","augment_subcommands_for_update","await_flag","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone_into","clone_into","fallback_height","fmt","fmt","fmt","from","from","from","from_arg_matches","from_arg_matches","from_arg_matches_mut","from_arg_matches_mut","has_subcommand","into","into","into","main","new_client","rpc_cookie","rpc_password","rpc_user","start_ctrlc_handler","to_owned","to_owned","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","update_from_arg_matches","update_from_arg_matches","update_from_arg_matches_mut","update_from_arg_matches_mut","url","vzip","vzip","vzip","rpc_args","rpc_args"],"q":["example_bitcoind_rpc_polling","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","example_bitcoind_rpc_polling::RpcCommands",""],"d":["","The mpsc channel bound for emissions from Emitter.","","Delay for committing to persistence.","","","","Sync by having the emitter logic in a separate thread","Delay between mempool emissions.","","","","Delay for printing status to stdout.","Syncs local state with remote state via RPC (starting from …","","","","","","","","","","","","","","","","","Starting block height to fallback to if no point of …","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","RPC auth cookie file","RPC auth password","RPC auth username","","","","","","","","","","","","","","","","","RPC URL","","","","",""],"i":[7,0,0,0,0,0,0,6,0,7,0,0,0,6,7,5,5,6,6,0,7,5,6,7,5,6,5,6,5,6,5,7,5,6,7,5,6,5,6,5,6,6,7,5,6,0,5,5,5,5,0,5,6,7,5,6,7,5,6,7,5,6,5,6,5,6,5,7,5,6,18,19],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[1,1],[1,1],[1,1],[1,1],[[2,3],4],[[]],[[]],[[]],[[]],[[]],[[]],[5,5],[6,6],[[]],[[]],0,[[7,8],9],[[5,8],9],[[6,8],9],[[]],[[]],[[]],[10,[[12,[5,11]]]],[10,[[12,[6,11]]]],[10,[[12,[5,11]]]],[10,[[12,[6,11]]]],[13,4],[[]],[[]],[[]],[[],14],[5,[[14,[15]]]],0,0,0,[[],[[16,[2]]]],[[]],[[]],[[],12],[[],12],[[],12],[[],12],[[],12],[[],12],[[],17],[[],17],[[],17],[[5,10],[[12,[11]]]],[[6,10],[[12,[11]]]],[[5,10],[[12,[11]]]],[[6,10],[[12,[11]]]],0,[[]],[[]],[[]],0,0],"p":[[6,"Command"],[3,"AtomicBool"],[3,"Duration"],[15,"bool"],[3,"RpcArgs"],[4,"RpcCommands"],[4,"Emission"],[3,"Formatter"],[6,"Result"],[3,"ArgMatches"],[3,"Error"],[4,"Result"],[15,"str"],[6,"Result"],[3,"Client"],[3,"Arc"],[3,"TypeId"],[13,"Sync"],[13,"Live"]]},\ "example_cli":{"doc":"","t":[13,4,3,13,13,13,4,4,3,13,13,3,13,4,6,6,13,13,13,13,13,13,13,6,13,13,13,4,2,12,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,2,11,11,11,11,11,11,11,11,11,11,11,12,12,5,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,5,11,11,11,12,12,12,5,12,11,11,11,11,11,11,11,11,11,11,12,12,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,12,12,12,12,12,12,12,12,12,12,12],"n":["Address","AddressCmd","Args","Balance","BranchAndBound","ChainSpecific","CoinSelectionAlgo","Commands","CreateTxChange","External","Index","Init","Internal","Keychain","KeychainChangeSet","KeychainTxGraph","LargestFirst","List","List","New","NewestFirst","Next","OldestFirst","PlannedUtxo","Send","SmallestFirst","TxOut","TxOutCmd","anyhow","args","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","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","change_descriptor","change_keychain","clap","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","command","cp_limit","create_tx","db","db_path","default","descriptor","deserialize","eq","equivalent","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","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","index","index","index_changeset","init","init_changeset","into","into","into","into","into","into","into","into","into_app","into_app_for_update","keymap","network","partial_cmp","planned_utxos","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_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","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","vzip","change","addr_cmd","address","chain_specific","coin_select","txout_cmd","value","confirmed","spent","unconfirmed","unspent"],"q":["example_cli","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","example_cli::AddressCmd","example_cli::Commands","","","","","","example_cli::TxOutCmd","","",""],"d":["Address generation and inspection.","","","Get the wallet balance.","","","","","","","Get last revealed address index for each keychain.","The initial state returned by init.","","","","","","List all addresses","List transaction outputs.","Get a new address regardless of the existing unused …","","Get the next unused address.","","","Send coins to an address.","","TxOut related commands.","","","Arguments parsed by the cli.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Persistence backend.","","","","","","","","","","","","","","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.","","","","","","","","","","","","","","","Keychain-txout index.","","Parses command line arguments and initializes all …","Initial changeset.","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).","","","Descriptor keymap.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","List change addresses","","Destination address","","","","Amount to send in satoshis","Return only confirmed outputs.","Return only spent outputs.","Return only unconfirmed outputs.","Return only unspent outputs."],"i":[5,0,0,5,6,5,0,0,0,9,7,0,9,0,0,0,6,7,8,7,6,7,6,0,5,6,5,0,0,28,22,22,5,7,8,5,7,8,0,37,28,22,5,6,7,8,9,37,28,22,5,6,7,8,9,22,37,0,5,6,7,8,9,5,6,7,8,9,9,22,22,0,28,22,6,22,9,9,9,5,6,6,7,8,9,9,37,28,22,5,6,7,8,9,22,5,7,8,22,5,7,8,6,0,5,7,8,37,28,37,0,28,37,28,22,5,6,7,8,9,22,22,28,22,9,0,9,5,6,7,8,9,6,9,37,28,22,5,6,7,8,9,37,28,22,5,6,7,8,9,37,28,22,5,6,7,8,9,22,5,7,8,22,5,7,8,37,28,22,5,6,7,8,9,38,39,40,40,40,41,40,42,42,42,42],"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,[1,1],[1,1],[1,1],[1,1],[1,1],[1,1],[1,1],[1,1],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,[[[5,[[0,[2,3]],[0,[2,4]]]]],[[5,[[0,[2,3]],[0,[2,4]]]]]],[6,6],[7,7],[8,8],[9,9],[[]],[[]],[[]],[[]],[[]],[[9,9],10],0,0,[[11,12,6,13,14],15],0,0,[[],6],0,[[],[[16,[9]]]],[[9,9],17],[[],17],[[[5,[[0,[18,3]],[0,[18,4]]]],19],20],[[6,19],20],[[6,19],20],[[7,19],20],[[8,19],20],[[9,19],20],[[9,19],20],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[21,[[16,[[22,[3,4]],23]]]],[21,[[16,[[5,[3,4]],23]]]],[21,[[16,[7,23]]]],[21,[[16,[8,23]]]],[21,[[16,[[22,[3,4]],23]]]],[21,[[16,[[5,[3,4]],23]]]],[21,[[16,[7,23]]]],[21,[[16,[8,23]]]],[24,[[16,[6]]]],[[25,25,25,12,26,27,[5,[3,4]]],15],[24,17],[24,17],[24,17],0,0,0,[24,[[15,[[28,[3,4]]]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],1],[[],1],0,0,[[9,9],[[29,[10]]]],[[11,30],[[16,[[34,[[33,[[0,[2,31]],32]]]]]]]],[9,16],[[]],[[]],[[]],[[]],[[]],[[],35],[[],35],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],16],[[],36],[[],36],[[],36],[[],36],[[],36],[[],36],[[],36],[[],36],[[[22,[3,4]],21],[[16,[23]]]],[[[5,[3,4]],21],[[16,[23]]]],[[7,21],[[16,[23]]]],[[8,21],[[16,[23]]]],[[[22,[3,4]],21],[[16,[23]]]],[[[5,[3,4]],21],[[16,[23]]]],[[7,21],[[16,[23]]]],[[8,21],[[16,[23]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0],"p":[[6,"Command"],[8,"Clone"],[8,"Subcommand"],[8,"Args"],[4,"Commands"],[4,"CoinSelectionAlgo"],[4,"AddressCmd"],[4,"TxOutCmd"],[4,"Keychain"],[4,"Ordering"],[6,"KeychainTxGraph"],[3,"BTreeMap"],[3,"Address"],[15,"u64"],[6,"Result"],[4,"Result"],[15,"bool"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[3,"ArgMatches"],[3,"Args"],[3,"Error"],[15,"str"],[3,"Mutex"],[4,"Network"],[8,"FnOnce"],[3,"Init"],[4,"Option"],[3,"Assets"],[8,"CanDerive"],[8,"Anchor"],[6,"PlannedUtxo"],[3,"Vec"],[3,"String"],[3,"TypeId"],[3,"CreateTxChange"],[13,"List"],[13,"Address"],[13,"Send"],[13,"TxOut"],[13,"List"]]},\ "example_electrum":{"doc":"","t":[6,17,17,3,4,13,3,13,11,11,11,11,11,11,12,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,5,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],"n":["ChangeSet","DB_MAGIC","DB_PATH","ElectrumArgs","ElectrumCommands","Scan","ScanOptions","Sync","augment_args","augment_args","augment_args_for_update","augment_args_for_update","augment_subcommands","augment_subcommands_for_update","batch_size","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","client","clone","clone","clone","clone_into","clone_into","clone_into","electrum_args","electrum_url","eq","fmt","fmt","fmt","from","from","from","from_arg_matches","from_arg_matches","from_arg_matches","from_arg_matches_mut","from_arg_matches_mut","from_arg_matches_mut","has_subcommand","into","into","into","into_app","into_app_for_update","main","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_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","vzip","vzip","vzip","all_spks","electrum_args","electrum_args","scan_options","scan_options","stop_gap","unconfirmed","unused_spks","utxos"],"q":["example_electrum","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","example_electrum::ElectrumCommands","","","","","","","",""],"d":["","","","","","Scans the addresses in the wallet using the electrum API.","","Scans particular addresses using the electrum API.","","","","","","","Set batch size for each script_history call to electrum …","","","","","","","","","","","","","","","The electrum url to use to connect to. If not provided it …","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","","","","","","Calls U::from(self).","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,0,0,0,0,6,0,6,2,7,2,7,6,6,7,6,2,7,6,2,7,2,6,2,7,6,2,7,6,2,7,6,2,7,6,2,7,6,2,7,6,2,7,6,6,2,7,7,7,0,6,2,7,6,2,7,6,2,7,6,2,7,6,2,7,6,2,7,6,2,7,16,17,16,17,16,17,16,16,16],"f":[0,0,0,0,0,0,0,0,[1,1],[1,1],[1,1],[1,1],[1,1],[1,1],0,[[]],[[]],[[]],[[]],[[]],[[]],[[2,3],[[5,[4]]]],[6,6],[2,2],[7,7],[[]],[[]],[[]],[6,2],0,[[7,7],8],[[6,9],10],[[2,9],10],[[7,9],10],[[]],[[]],[[]],[11,[[13,[6,12]]]],[11,[[13,[2,12]]]],[11,[[13,[7,12]]]],[11,[[13,[6,12]]]],[11,[[13,[2,12]]]],[11,[[13,[7,12]]]],[14,8],[[]],[[]],[[]],[[],1],[[],1],[[],5],[[]],[[]],[[]],[[],13],[[],13],[[],13],[[],13],[[],13],[[],13],[[],15],[[],15],[[],15],[[6,11],[[13,[12]]]],[[2,11],[[13,[12]]]],[[7,11],[[13,[12]]]],[[6,11],[[13,[12]]]],[[2,11],[[13,[12]]]],[[7,11],[[13,[12]]]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0],"p":[[6,"Command"],[3,"ElectrumArgs"],[4,"Network"],[3,"Client"],[6,"Result"],[4,"ElectrumCommands"],[3,"ScanOptions"],[15,"bool"],[3,"Formatter"],[6,"Result"],[3,"ArgMatches"],[3,"Error"],[4,"Result"],[15,"str"],[3,"TypeId"],[13,"Sync"],[13,"Scan"]]},\ @@ -17,7 +17,7 @@ var searchIndex = JSON.parse('{\ "wallet_electrum_example":{"doc":"","t":[17,17,17,17,5],"n":["BATCH_SIZE","DB_MAGIC","SEND_AMOUNT","STOP_GAP","main"],"q":["wallet_electrum_example","","","",""],"d":["","","","",""],"i":[0,0,0,0,0],"f":[0,0,0,0,[[],[[2,[1]]]]],"p":[[3,"Error"],[4,"Result"]]},\ "wallet_esplora_async":{"doc":"","t":[17,17,17,17,5],"n":["DB_MAGIC","PARALLEL_REQUESTS","SEND_AMOUNT","STOP_GAP","main"],"q":["wallet_esplora_async","","","",""],"d":["","","","",""],"i":[0,0,0,0,0],"f":[0,0,0,0,[[],[[2,[1]]]]],"p":[[3,"Error"],[4,"Result"]]},\ "wallet_esplora_blocking":{"doc":"","t":[17,17,17,17,5],"n":["DB_MAGIC","PARALLEL_REQUESTS","SEND_AMOUNT","STOP_GAP","main"],"q":["wallet_esplora_blocking","","","",""],"d":["","","","",""],"i":[0,0,0,0,0],"f":[0,0,0,0,[[],[[2,[1]]]]],"p":[[3,"Error"],[4,"Result"]]},\ -"wallet_rpc":{"doc":"","t":[3,13,17,4,13,13,11,11,11,11,11,11,12,11,12,12,11,11,11,11,11,11,11,11,11,11,5,12,12,12,12,12,11,11,11,11,11,11,11,11,12,11,11],"n":["Args","Block","DB_MAGIC","Emission","Mempool","SigTerm","augment_args","augment_args_for_update","borrow","borrow","borrow_mut","borrow_mut","change_descriptor","client","db_path","descriptor","fmt","fmt","from","from","from_arg_matches","from_arg_matches_mut","into","into","into_app","into_app_for_update","main","network","rpc_cookie","rpc_pass","rpc_user","start_height","try_from","try_from","try_into","try_into","type_id","type_id","update_from_arg_matches","update_from_arg_matches_mut","url","vzip","vzip"],"q":["wallet_rpc","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Bitcoind RPC example using bdk::Wallet.","","","","","","","","","","","","Wallet change descriptor","","Where to store wallet data","Wallet descriptor","","","Returns the argument unchanged.","Returns the argument unchanged.","","","Calls U::from(self).","Calls U::from(self).","","","","Bitcoin network to connect to","RPC auth cookie file","RPC auth password","RPC auth username","Earliest block height to start sync from","","","","","","","","","RPC URL","",""],"i":[0,7,0,0,7,7,2,2,2,7,2,7,2,2,2,2,2,7,2,7,2,2,2,7,2,2,0,2,2,2,2,2,2,7,2,7,2,7,2,2,2,2,7],"f":[0,0,0,0,0,0,[1,1],[1,1],[[]],[[]],[[]],[[]],0,[2,[[4,[3]]]],0,0,[[2,5],6],[[7,5],6],[[]],[[]],[8,[[10,[2,9]]]],[8,[[10,[2,9]]]],[[]],[[]],[[],1],[[],1],[[],4],0,0,0,0,0,[[],10],[[],10],[[],10],[[],10],[[],11],[[],11],[[2,8],[[10,[9]]]],[[2,8],[[10,[9]]]],0,[[]],[[]]],"p":[[6,"Command"],[3,"Args"],[3,"Client"],[6,"Result"],[3,"Formatter"],[6,"Result"],[4,"Emission"],[3,"ArgMatches"],[3,"Error"],[4,"Result"],[3,"TypeId"]]}\ +"wallet_rpc":{"doc":"","t":[3,13,17,4,13,13,11,11,11,11,11,11,12,11,12,12,11,11,11,11,11,11,11,11,11,11,5,12,12,12,12,12,11,11,11,11,11,11,11,11,12,11,11],"n":["Args","Block","DB_MAGIC","Emission","Mempool","SigTerm","augment_args","augment_args_for_update","borrow","borrow","borrow_mut","borrow_mut","change_descriptor","client","db_path","descriptor","fmt","fmt","from","from","from_arg_matches","from_arg_matches_mut","into","into","into_app","into_app_for_update","main","network","rpc_cookie","rpc_pass","rpc_user","start_height","try_from","try_from","try_into","try_into","type_id","type_id","update_from_arg_matches","update_from_arg_matches_mut","url","vzip","vzip"],"q":["wallet_rpc","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Bitcoind RPC example using bdk_wallet::Wallet.","","","","","","","","","","","","Wallet change descriptor","","Where to store wallet data","Wallet descriptor","","","Returns the argument unchanged.","Returns the argument unchanged.","","","Calls U::from(self).","Calls U::from(self).","","","","Bitcoin network to connect to","RPC auth cookie file","RPC auth password","RPC auth username","Earliest block height to start sync from","","","","","","","","","RPC URL","",""],"i":[0,7,0,0,7,7,2,2,2,7,2,7,2,2,2,2,2,7,2,7,2,2,2,7,2,2,0,2,2,2,2,2,2,7,2,7,2,7,2,2,2,2,7],"f":[0,0,0,0,0,0,[1,1],[1,1],[[]],[[]],[[]],[[]],0,[2,[[4,[3]]]],0,0,[[2,5],6],[[7,5],6],[[]],[[]],[8,[[10,[2,9]]]],[8,[[10,[2,9]]]],[[]],[[]],[[],1],[[],1],[[],4],0,0,0,0,0,[[],10],[[],10],[[],10],[[],10],[[],11],[[],11],[[2,8],[[10,[9]]]],[[2,8],[[10,[9]]]],0,[[]],[[]]],"p":[[6,"Command"],[3,"Args"],[3,"Client"],[6,"Result"],[3,"Formatter"],[6,"Result"],[4,"Emission"],[3,"ArgMatches"],[3,"Error"],[4,"Result"],[3,"TypeId"]]}\ }'); 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 dcd0579fb8..aaac72d2fe 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.html @@ -1 +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 b7e6fb64d7..ca4e884b90 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,5 +1,4 @@ var sourcesIndex = JSON.parse('{\ -"bdk":["",[["descriptor",[],["checksum.rs","dsl.rs","error.rs","mod.rs","policy.rs","template.rs"]],["keys",[],["mod.rs"]],["psbt",[],["mod.rs"]],["wallet",[],["coin_selection.rs","error.rs","export.rs","mod.rs","signer.rs","tx_builder.rs","utils.rs"]]],["lib.rs","types.rs"]],\ "bdk_bitcoind_rpc":["",[],["lib.rs"]],\ "bdk_chain":["",[["keychain",[],["txout_index.rs"]]],["chain_data.rs","chain_oracle.rs","descriptor_ext.rs","example_utils.rs","indexed_tx_graph.rs","keychain.rs","lib.rs","local_chain.rs","spk_client.rs","spk_iter.rs","spk_txout_index.rs","tx_data_traits.rs","tx_graph.rs"]],\ "bdk_coin_select":["",[],["bnb.rs","coin_selector.rs","lib.rs"]],\ @@ -10,6 +9,7 @@ var sourcesIndex = JSON.parse('{\ "bdk_persist":["",[],["lib.rs","persist.rs"]],\ "bdk_testenv":["",[],["lib.rs"]],\ "bdk_tmp_plan":["",[],["lib.rs","plan_impls.rs","requirements.rs","template.rs"]],\ +"bdk_wallet":["",[["descriptor",[],["checksum.rs","dsl.rs","error.rs","mod.rs","policy.rs","template.rs"]],["keys",[],["mod.rs"]],["psbt",[],["mod.rs"]],["wallet",[],["coin_selection.rs","error.rs","export.rs","mod.rs","signer.rs","tx_builder.rs","utils.rs"]]],["lib.rs","types.rs"]],\ "example_bitcoind_rpc_polling":["",[],["main.rs"]],\ "example_cli":["",[],["lib.rs"]],\ "example_electrum":["",[],["main.rs"]],\ 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 deleted file mode 100644 index 16da53cad9..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html +++ /dev/null @@ -1,297 +0,0 @@ -checksum.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
-
// 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.
-
-//! Descriptor checksum
-//!
-//! This module contains a re-implementation of the function used by Bitcoin Core to calculate the
-//! 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";
-
-fn poly_mod(mut c: u64, val: u64) -> u64 {
-    let c0 = c >> 35;
-    c = ((c & 0x7ffffffff) << 5) ^ val;
-    if c0 & 1 > 0 {
-        c ^= 0xf5dee51989
-    };
-    if c0 & 2 > 0 {
-        c ^= 0xa9fdca3312
-    };
-    if c0 & 4 > 0 {
-        c ^= 0x1bab10e32d
-    };
-    if c0 & 8 > 0 {
-        c ^= 0x3706b1677a
-    };
-    if c0 & 16 > 0 {
-        c ^= 0x644d626ffd
-    };
-
-    c
-}
-
-/// Compute the checksum bytes of a descriptor, excludes any existing checksum in the descriptor string from the calculation
-pub fn calc_checksum_bytes(mut desc: &str) -> Result<[u8; 8], DescriptorError> {
-    let mut c = 1;
-    let mut cls = 0;
-    let mut clscount = 0;
-
-    let mut original_checksum = None;
-    if let Some(split) = desc.split_once('#') {
-        desc = split.0;
-        original_checksum = Some(split.1);
-    }
-
-    for ch in desc.as_bytes() {
-        let pos = INPUT_CHARSET
-            .iter()
-            .position(|b| b == ch)
-            .ok_or(DescriptorError::InvalidDescriptorCharacter(*ch))? as u64;
-        c = poly_mod(c, pos & 31);
-        cls = cls * 3 + (pos >> 5);
-        clscount += 1;
-        if clscount == 3 {
-            c = poly_mod(c, cls);
-            cls = 0;
-            clscount = 0;
-        }
-    }
-    if clscount > 0 {
-        c = poly_mod(c, cls);
-    }
-    (0..8).for_each(|_| c = poly_mod(c, 0));
-    c ^= 1;
-
-    let mut checksum = [0_u8; 8];
-    for j in 0..8 {
-        checksum[j] = CHECKSUM_CHARSET[((c >> (5 * (7 - j))) & 31) as usize];
-    }
-
-    // if input data already had a checksum, check calculated checksum against original checksum
-    if let Some(original_checksum) = original_checksum {
-        if original_checksum.as_bytes() != checksum {
-            return Err(DescriptorError::InvalidDescriptorChecksum);
-        }
-    }
-
-    Ok(checksum)
-}
-
-/// Compute the checksum of a descriptor, excludes any existing checksum in the descriptor string from the calculation
-pub fn calc_checksum(desc: &str) -> Result<String, DescriptorError> {
-    // unsafe is okay here as the checksum only uses bytes in `CHECKSUM_CHARSET`
-    calc_checksum_bytes(desc).map(|b| unsafe { String::from_utf8_unchecked(b.to_vec()) })
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use crate::descriptor::calc_checksum;
-    use assert_matches::assert_matches;
-
-    // test calc_checksum() function; it should return the same value as Bitcoin Core
-    #[test]
-    fn test_calc_checksum() {
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)";
-        assert_eq!(calc_checksum(desc).unwrap(), "tqz0nc62");
-
-        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)";
-        assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs");
-    }
-
-    // test calc_checksum() function; it should return the same value as Bitcoin Core even if the
-    // descriptor string includes a checksum hash
-    #[test]
-    fn test_calc_checksum_with_checksum_hash() {
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc62";
-        assert_eq!(calc_checksum(desc).unwrap(), "tqz0nc62");
-
-        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)#lasegmfs";
-        assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs");
-
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc26";
-        assert_matches!(
-            calc_checksum(desc),
-            Err(DescriptorError::InvalidDescriptorChecksum)
-        );
-
-        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)#lasegmsf";
-        assert_matches!(
-            calc_checksum(desc),
-            Err(DescriptorError::InvalidDescriptorChecksum)
-        );
-    }
-
-    #[test]
-    fn test_calc_checksum_invalid_character() {
-        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!(
-            calc_checksum(&invalid_desc),
-            Err(DescriptorError::InvalidDescriptorCharacter(invalid_char)) if invalid_char == sparkle_heart.as_bytes()[0]
-        );
-    }
-}
-
-
\ No newline at end of file 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 deleted file mode 100644 index 0be56f2dd7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/dsl.rs.html +++ /dev/null @@ -1,2435 +0,0 @@ -dsl.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
-1148
-1149
-1150
-1151
-1152
-1153
-1154
-1155
-1156
-1157
-1158
-1159
-1160
-1161
-1162
-1163
-1164
-1165
-1166
-1167
-1168
-1169
-1170
-1171
-1172
-1173
-1174
-1175
-1176
-1177
-1178
-1179
-1180
-1181
-1182
-1183
-1184
-1185
-1186
-1187
-1188
-1189
-1190
-1191
-1192
-1193
-1194
-1195
-1196
-1197
-1198
-1199
-1200
-1201
-1202
-1203
-1204
-1205
-1206
-1207
-1208
-1209
-1210
-1211
-1212
-1213
-1214
-1215
-1216
-
// 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.
-
-//! Descriptors DSL
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! impl_top_level_sh {
-    // disallow `sortedmulti` in `bare()`
-    ( Bare, new, new, Legacy, sortedmulti $( $inner:tt )* ) => {
-        compile_error!("`bare()` descriptors can't contain any `sortedmulti()` operands");
-    };
-    ( Bare, new, new, Legacy, sortedmulti_vec $( $inner:tt )* ) => {
-        compile_error!("`bare()` descriptors can't contain any `sortedmulti_vec()` operands");
-    };
-
-    ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, sortedmulti $( $inner:tt )* ) => {{
-        use core::marker::PhantomData;
-
-        use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
-        use $crate::miniscript::$ctx;
-
-        let build_desc = |k, pks| {
-            Ok((Descriptor::<DescriptorPublicKey>::$inner_struct($inner_struct::$sortedmulti_constructor(k, pks)?), PhantomData::<$ctx>))
-        };
-
-        $crate::impl_sortedmulti!(build_desc, sortedmulti $( $inner )*)
-    }};
-    ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, sortedmulti_vec $( $inner:tt )* ) => {{
-        use core::marker::PhantomData;
-
-        use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
-        use $crate::miniscript::$ctx;
-
-        let build_desc = |k, pks| {
-            Ok((Descriptor::<DescriptorPublicKey>::$inner_struct($inner_struct::$sortedmulti_constructor(k, pks)?), PhantomData::<$ctx>))
-        };
-
-        $crate::impl_sortedmulti!(build_desc, sortedmulti_vec $( $inner )*)
-    }};
-
-    ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, $( $minisc:tt )* ) => {{
-        use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
-
-        $crate::fragment!($( $minisc )*)
-            .and_then(|(minisc, keymap, networks)| Ok(($inner_struct::$constructor(minisc)?, keymap, networks)))
-            .and_then(|(inner, key_map, valid_networks)| Ok((Descriptor::<DescriptorPublicKey>::$inner_struct(inner), key_map, valid_networks)))
-    }};
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! impl_top_level_pk {
-    ( $inner_type:ident, $ctx:ty, $key:expr ) => {{
-        use $crate::miniscript::descriptor::$inner_type;
-
-        #[allow(unused_imports)]
-        use $crate::keys::{DescriptorKey, IntoDescriptorKey};
-        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
-
-        $key.into_descriptor_key()
-            .and_then(|key: DescriptorKey<$ctx>| key.extract(&secp))
-            .map_err($crate::descriptor::DescriptorError::Key)
-            .map(|(pk, key_map, valid_networks)| ($inner_type::new(pk), key_map, valid_networks))
-    }};
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! impl_top_level_tr {
-    ( $internal_key:expr, $tap_tree:expr ) => {{
-        use $crate::miniscript::descriptor::{
-            Descriptor, DescriptorPublicKey, KeyMap, TapTree, Tr,
-        };
-        use $crate::miniscript::Tap;
-
-        #[allow(unused_imports)]
-        use $crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
-
-        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
-
-        $internal_key
-            .into_descriptor_key()
-            .and_then(|key: DescriptorKey<Tap>| key.extract(&secp))
-            .map_err($crate::descriptor::DescriptorError::Key)
-            .and_then(|(pk, mut key_map, mut valid_networks)| {
-                let tap_tree = $tap_tree.map(
-                    |(tap_tree, tree_keymap, tree_networks): (
-                        TapTree<DescriptorPublicKey>,
-                        KeyMap,
-                        ValidNetworks,
-                    )| {
-                        key_map.extend(tree_keymap.into_iter());
-                        valid_networks =
-                            $crate::keys::merge_networks(&valid_networks, &tree_networks);
-
-                        tap_tree
-                    },
-                );
-
-                Ok((
-                    Descriptor::<DescriptorPublicKey>::Tr(Tr::new(pk, tap_tree)?),
-                    key_map,
-                    valid_networks,
-                ))
-            })
-    }};
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! impl_leaf_opcode {
-    ( $terminal_variant:ident ) => {{
-        use $crate::descriptor::CheckMiniscript;
-
-        $crate::miniscript::Miniscript::from_ast(
-            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant,
-        )
-        .map_err($crate::descriptor::DescriptorError::Miniscript)
-        .and_then(|minisc| {
-            minisc.check_miniscript()?;
-            Ok(minisc)
-        })
-        .map(|minisc| {
-            (
-                minisc,
-                $crate::miniscript::descriptor::KeyMap::default(),
-                $crate::keys::any_network(),
-            )
-        })
-    }};
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! impl_leaf_opcode_value {
-    ( $terminal_variant:ident, $value:expr ) => {{
-        use $crate::descriptor::CheckMiniscript;
-
-        $crate::miniscript::Miniscript::from_ast(
-            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($value),
-        )
-        .map_err($crate::descriptor::DescriptorError::Miniscript)
-        .and_then(|minisc| {
-            minisc.check_miniscript()?;
-            Ok(minisc)
-        })
-        .map(|minisc| {
-            (
-                minisc,
-                $crate::miniscript::descriptor::KeyMap::default(),
-                $crate::keys::any_network(),
-            )
-        })
-    }};
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! impl_leaf_opcode_value_two {
-    ( $terminal_variant:ident, $one:expr, $two:expr ) => {{
-        use $crate::descriptor::CheckMiniscript;
-
-        $crate::miniscript::Miniscript::from_ast(
-            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($one, $two),
-        )
-        .map_err($crate::descriptor::DescriptorError::Miniscript)
-        .and_then(|minisc| {
-            minisc.check_miniscript()?;
-            Ok(minisc)
-        })
-        .map(|minisc| {
-            (
-                minisc,
-                $crate::miniscript::descriptor::KeyMap::default(),
-                $crate::keys::any_network(),
-            )
-        })
-    }};
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! impl_node_opcode_two {
-    ( $terminal_variant:ident, $( $inner:tt )* ) => ({
-        use $crate::descriptor::CheckMiniscript;
-
-        let inner = $crate::fragment_internal!( @t $( $inner )* );
-        let (a, b) = $crate::descriptor::dsl::TupleTwo::from(inner).flattened();
-
-        a
-            .and_then(|a| Ok((a, b?)))
-            .and_then(|((a_minisc, mut a_keymap, a_networks), (b_minisc, b_keymap, b_networks))| {
-                // join key_maps
-                a_keymap.extend(b_keymap.into_iter());
-
-                let minisc = $crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
-                    $crate::alloc::sync::Arc::new(a_minisc),
-                    $crate::alloc::sync::Arc::new(b_minisc),
-                ))?;
-
-                minisc.check_miniscript()?;
-
-                Ok((minisc, a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
-            })
-    });
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! impl_node_opcode_three {
-    ( $terminal_variant:ident, $( $inner:tt )* ) => ({
-        use $crate::descriptor::CheckMiniscript;
-
-        let inner = $crate::fragment_internal!( @t $( $inner )* );
-        let (a, b, c) = $crate::descriptor::dsl::TupleThree::from(inner).flattened();
-
-        a
-            .and_then(|a| Ok((a, b?, c?)))
-            .and_then(|((a_minisc, mut a_keymap, a_networks), (b_minisc, b_keymap, b_networks), (c_minisc, c_keymap, c_networks))| {
-                // join key_maps
-                a_keymap.extend(b_keymap.into_iter());
-                a_keymap.extend(c_keymap.into_iter());
-
-                let networks = $crate::keys::merge_networks(&a_networks, &b_networks);
-                let networks = $crate::keys::merge_networks(&networks, &c_networks);
-
-                let minisc = $crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
-                    $crate::alloc::sync::Arc::new(a_minisc),
-                    $crate::alloc::sync::Arc::new(b_minisc),
-                    $crate::alloc::sync::Arc::new(c_minisc),
-                ))?;
-
-                minisc.check_miniscript()?;
-
-                Ok((minisc, a_keymap, networks))
-            })
-    });
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! impl_sortedmulti {
-    ( $build_desc:expr, sortedmulti_vec ( $thresh:expr, $keys:expr ) ) => ({
-        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
-        $crate::keys::make_sortedmulti($thresh, $keys, $build_desc, &secp)
-    });
-    ( $build_desc:expr, sortedmulti ( $thresh:expr $(, $key:expr )+ ) ) => ({
-        use $crate::keys::IntoDescriptorKey;
-        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
-
-        let keys = vec![
-            $(
-                $key.into_descriptor_key(),
-            )*
-        ];
-
-        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))
-    });
-
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! parse_tap_tree {
-    ( @merge $tree_a:expr, $tree_b:expr) => {{
-        use $crate::miniscript::descriptor::TapTree;
-
-        $tree_a
-            .and_then(|tree_a| Ok((tree_a, $tree_b?)))
-            .and_then(|((a_tree, mut a_keymap, a_networks), (b_tree, b_keymap, b_networks))| {
-                a_keymap.extend(b_keymap.into_iter());
-                Ok((TapTree::combine(a_tree, b_tree), a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
-            })
-
-    }};
-
-    // Two sub-trees
-    ( { { $( $tree_a:tt )* }, { $( $tree_b:tt )* } } ) => {{
-        let tree_a = $crate::parse_tap_tree!( { $( $tree_a )* } );
-        let tree_b = $crate::parse_tap_tree!( { $( $tree_b )* } );
-
-        $crate::parse_tap_tree!(@merge tree_a, tree_b)
-    }};
-
-    // One leaf and a sub-tree
-    ( { $op_a:ident ( $( $minisc_a:tt )* ), { $( $tree_b:tt )* } } ) => {{
-        let tree_a = $crate::parse_tap_tree!( $op_a ( $( $minisc_a )* ) );
-        let tree_b = $crate::parse_tap_tree!( { $( $tree_b )* } );
-
-        $crate::parse_tap_tree!(@merge tree_a, tree_b)
-    }};
-    ( { { $( $tree_a:tt )* }, $op_b:ident ( $( $minisc_b:tt )* ) } ) => {{
-        let tree_a = $crate::parse_tap_tree!( { $( $tree_a )* } );
-        let tree_b = $crate::parse_tap_tree!( $op_b ( $( $minisc_b )* ) );
-
-        $crate::parse_tap_tree!(@merge tree_a, tree_b)
-    }};
-
-    // Two leaves
-    ( { $op_a:ident ( $( $minisc_a:tt )* ), $op_b:ident ( $( $minisc_b:tt )* ) } ) => {{
-        let tree_a = $crate::parse_tap_tree!( $op_a ( $( $minisc_a )* ) );
-        let tree_b = $crate::parse_tap_tree!( $op_b ( $( $minisc_b )* ) );
-
-        $crate::parse_tap_tree!(@merge tree_a, tree_b)
-    }};
-
-    // Single leaf
-    ( $op:ident ( $( $minisc:tt )* ) ) => {{
-        use $crate::alloc::sync::Arc;
-        use $crate::miniscript::descriptor::TapTree;
-
-        $crate::fragment!( $op ( $( $minisc )* ) )
-            .map(|(a_minisc, a_keymap, a_networks)| (TapTree::Leaf(Arc::new(a_minisc)), a_keymap, a_networks))
-    }};
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! apply_modifier {
-    ( $terminal_variant:ident, $inner:expr ) => {{
-        use $crate::descriptor::CheckMiniscript;
-
-        $inner
-            .map_err(|e| -> $crate::descriptor::DescriptorError { e.into() })
-            .and_then(|(minisc, keymap, networks)| {
-                let minisc = $crate::miniscript::Miniscript::from_ast(
-                    $crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
-                        $crate::alloc::sync::Arc::new(minisc),
-                    ),
-                )?;
-
-                minisc.check_miniscript()?;
-
-                Ok((minisc, keymap, networks))
-            })
-    }};
-
-    ( a: $inner:expr ) => {{
-        $crate::apply_modifier!(Alt, $inner)
-    }};
-    ( s: $inner:expr ) => {{
-        $crate::apply_modifier!(Swap, $inner)
-    }};
-    ( c: $inner:expr ) => {{
-        $crate::apply_modifier!(Check, $inner)
-    }};
-    ( d: $inner:expr ) => {{
-        $crate::apply_modifier!(DupIf, $inner)
-    }};
-    ( v: $inner:expr ) => {{
-        $crate::apply_modifier!(Verify, $inner)
-    }};
-    ( j: $inner:expr ) => {{
-        $crate::apply_modifier!(NonZero, $inner)
-    }};
-    ( n: $inner:expr ) => {{
-        $crate::apply_modifier!(ZeroNotEqual, $inner)
-    }};
-
-    // Modifiers expanded to other operators
-    ( t: $inner:expr ) => {{
-        $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
-            $crate::impl_leaf_opcode_value_two!(
-                AndV,
-                $crate::alloc::sync::Arc::new(a_minisc),
-                $crate::alloc::sync::Arc::new($crate::fragment!(true).unwrap().0)
-            )
-            .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
-        })
-    }};
-    ( l: $inner:expr ) => {{
-        $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
-            $crate::impl_leaf_opcode_value_two!(
-                OrI,
-                $crate::alloc::sync::Arc::new($crate::fragment!(false).unwrap().0),
-                $crate::alloc::sync::Arc::new(a_minisc)
-            )
-            .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
-        })
-    }};
-    ( u: $inner:expr ) => {{
-        $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
-            $crate::impl_leaf_opcode_value_two!(
-                OrI,
-                $crate::alloc::sync::Arc::new(a_minisc),
-                $crate::alloc::sync::Arc::new($crate::fragment!(false).unwrap().0)
-            )
-            .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
-        })
-    }};
-}
-
-/// Macro to write full descriptors with code
-///
-/// This macro expands to a `Result` of
-/// [`DescriptorTemplateOut`](super::template::DescriptorTemplateOut) and [`DescriptorError`](crate::descriptor::DescriptorError)
-///
-/// The syntax is very similar to the normal descriptor syntax, with the exception that modifiers
-/// cannot be grouped together. For instance, a descriptor fragment like `sdv:older(144)` has to be
-/// broken up to `s:d:v:older(144)`.
-///
-/// The `pk()`, `pk_k()` and `pk_h()` operands can take as argument any type that implements
-/// [`IntoDescriptorKey`]. This means that keys can also be written inline as strings, but in that
-/// case they must be wrapped in quotes, which is another difference compared to the standard
-/// descriptor syntax.
-///
-/// [`IntoDescriptorKey`]: crate::keys::IntoDescriptorKey
-///
-/// ## Example
-///
-/// Signature plus timelock descriptor:
-///
-/// ```
-/// # use std::str::FromStr;
-/// let (my_descriptor, my_keys_map, networks) = bdk::descriptor!(sh(wsh(and_v(v:pk("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"),older(50)))))?;
-/// # Ok::<(), Box<dyn std::error::Error>>(())
-/// ```
-///
-/// -------
-///
-/// 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.
-///
-/// They both produce the descriptor: `wsh(thresh(2,pk(...),s:pk(...),sndv:older(...)))`
-///
-/// ```
-/// # use std::str::FromStr;
-/// let my_key_1 = bitcoin::PublicKey::from_str(
-///     "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
-/// )?;
-/// let my_key_2 =
-///     bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
-/// let my_timelock = 50;
-///
-/// let (descriptor_a, key_map_a, networks) = bdk::descriptor! {
-///     wsh (
-///         thresh(2, pk(my_key_1), s:pk(my_key_2), s:n:d:v:older(my_timelock))
-///     )
-/// }?;
-///
-/// #[rustfmt::skip]
-/// let b_items = vec![
-///     bdk::fragment!(pk(my_key_1))?,
-///     bdk::fragment!(s:pk(my_key_2))?,
-///     bdk::fragment!(s:n:d:v:older(my_timelock))?,
-/// ];
-/// let (descriptor_b, mut key_map_b, networks) = bdk::descriptor!(wsh(thresh_vec(2, b_items)))?;
-///
-/// assert_eq!(descriptor_a, descriptor_b);
-/// assert_eq!(key_map_a.len(), key_map_b.len());
-/// # Ok::<(), Box<dyn std::error::Error>>(())
-/// ```
-///
-/// ------
-///
-/// Simple 2-of-2 multi-signature, equivalent to: `wsh(multi(2, ...))`
-///
-/// ```
-/// # use std::str::FromStr;
-/// let my_key_1 = bitcoin::PublicKey::from_str(
-///     "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
-/// )?;
-/// let my_key_2 =
-///     bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
-///
-/// let (descriptor, key_map, networks) = bdk::descriptor! {
-///     wsh (
-///         multi(2, my_key_1, my_key_2)
-///     )
-/// }?;
-/// # Ok::<(), Box<dyn std::error::Error>>(())
-/// ```
-///
-/// ------
-///
-/// Native-Segwit single-sig, equivalent to: `wpkh(...)`
-///
-/// ```
-/// let my_key =
-///     bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
-///
-/// 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 )* ) ) => ({
-        $crate::impl_top_level_sh!(Bare, new, new, Legacy, $( $minisc )*)
-    });
-    ( sh ( wsh ( $( $minisc:tt )* ) ) ) => ({
-        $crate::descriptor!(shwsh ($( $minisc )*))
-    });
-    ( shwsh ( $( $minisc:tt )* ) ) => ({
-        $crate::impl_top_level_sh!(Sh, new_wsh, new_wsh_sortedmulti, Segwitv0, $( $minisc )*)
-    });
-    ( pk ( $key:expr ) ) => ({
-        // `pk()` is actually implemented as `bare(pk())`
-        $crate::descriptor!( bare ( pk ( $key ) ) )
-    });
-    ( pkh ( $key:expr ) ) => ({
-        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
-
-        $crate::impl_top_level_pk!(Pkh, $crate::miniscript::Legacy, $key)
-            .and_then(|(a, b, c)| Ok((a.map_err(|e| miniscript::Error::from(e))?, b, c)))
-            .map(|(a, b, c)| (Descriptor::<DescriptorPublicKey>::Pkh(a), b, c))
-    });
-    ( wpkh ( $key:expr ) ) => ({
-        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
-
-        $crate::impl_top_level_pk!(Wpkh, $crate::miniscript::Segwitv0, $key)
-            .and_then(|(a, b, c)| Ok((a.map_err(|e| miniscript::Error::from(e))?, b, c)))
-            .map(|(a, b, c)| (Descriptor::<DescriptorPublicKey>::Wpkh(a), b, c))
-    });
-    ( sh ( wpkh ( $key:expr ) ) ) => ({
-        $crate::descriptor!(shwpkh ( $key ))
-    });
-    ( shwpkh ( $key:expr ) ) => ({
-        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey, Sh};
-
-        $crate::impl_top_level_pk!(Wpkh, $crate::miniscript::Segwitv0, $key)
-            .and_then(|(a, b, c)| Ok((a.map_err(|e| miniscript::Error::from(e))?, b, c)))
-            .and_then(|(a, b, c)| Ok((Descriptor::<DescriptorPublicKey>::Sh(Sh::new_wpkh(a.into_inner())?), b, c)))
-    });
-    ( sh ( $( $minisc:tt )* ) ) => ({
-        $crate::impl_top_level_sh!(Sh, new, new_sortedmulti, Legacy, $( $minisc )*)
-    });
-    ( wsh ( $( $minisc:tt )* ) ) => ({
-        $crate::impl_top_level_sh!(Wsh, new, new_sortedmulti, Segwitv0, $( $minisc )*)
-    });
-
-    ( tr ( $internal_key:expr ) ) => ({
-        $crate::impl_top_level_tr!($internal_key, None)
-    });
-    ( tr ( $internal_key:expr, $( $taptree:tt )* ) ) => ({
-        let tap_tree = $crate::parse_tap_tree!( $( $taptree )* );
-        tap_tree
-            .and_then(|tap_tree| $crate::impl_top_level_tr!($internal_key, Some(tap_tree)))
-    });
-}
-
-#[doc(hidden)]
-pub struct TupleTwo<A, B> {
-    pub a: A,
-    pub b: B,
-}
-
-impl<A, B> TupleTwo<A, B> {
-    pub fn flattened(self) -> (A, B) {
-        (self.a, self.b)
-    }
-}
-
-impl<A, B> From<(A, (B, ()))> for TupleTwo<A, B> {
-    fn from((a, (b, _)): (A, (B, ()))) -> Self {
-        TupleTwo { a, b }
-    }
-}
-
-#[doc(hidden)]
-pub struct TupleThree<A, B, C> {
-    pub a: A,
-    pub b: B,
-    pub c: C,
-}
-
-impl<A, B, C> TupleThree<A, B, C> {
-    pub fn flattened(self) -> (A, B, C) {
-        (self.a, self.b, self.c)
-    }
-}
-
-impl<A, B, C> From<(A, (B, (C, ())))> for TupleThree<A, B, C> {
-    fn from((a, (b, (c, _))): (A, (B, (C, ())))) -> Self {
-        TupleThree { a, b, c }
-    }
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! group_multi_keys {
-    ( $( $key:expr ),+ ) => {{
-        use $crate::keys::IntoDescriptorKey;
-
-        let keys = vec![
-            $(
-                $key.into_descriptor_key(),
-            )*
-        ];
-
-        keys.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
-            .map_err($crate::descriptor::DescriptorError::Key)
-    }};
-}
-
-#[doc(hidden)]
-#[macro_export]
-macro_rules! fragment_internal {
-    // The @v prefix is used to parse a sequence of operands and return them in a vector. This is
-    // used by operands that take a variable number of arguments, like `thresh()` and `multi()`.
-    ( @v $op:ident ( $( $args:tt )* ) $( $tail:tt )* ) => ({
-        let mut v = vec![$crate::fragment!( $op ( $( $args )* ) )];
-        v.append(&mut $crate::fragment_internal!( @v $( $tail )* ));
-
-        v
-    });
-    // Match modifiers
-    ( @v $modif:tt : $( $tail:tt )* ) => ({
-        let mut v = $crate::fragment_internal!( @v $( $tail )* );
-        let first = v.drain(..1).next().unwrap();
-
-        let first = $crate::apply_modifier!($modif:first);
-
-        let mut v_final = vec![first];
-        v_final.append(&mut v);
-
-        v_final
-    });
-    // Remove commas between operands
-    ( @v , $( $tail:tt )* ) => ({
-        $crate::fragment_internal!( @v $( $tail )* )
-    });
-    ( @v ) => ({
-        vec![]
-    });
-
-    // The @t prefix is used to parse a sequence of operands and return them in a tuple. This
-    // allows checking at compile-time the number of arguments passed to an operand. For this
-    // reason it's used by `and_*()`, `or_*()`, etc.
-    //
-    // Unfortunately, due to the fact that concatenating tuples is pretty hard, the final result
-    // adds in the first spot the parsed operand and in the second spot the result of parsing
-    // all the following ones. For two operands the type then corresponds to: (X, (X, ())). For
-    // three operands it's (X, (X, (X, ()))), etc.
-    //
-    // To check that the right number of arguments has been passed we can "cast" those tuples to
-    // more convenient structures like `TupleTwo`. If the conversion succeeds, the right number of
-    // args was passed. Otherwise the compilation fails entirely.
-    ( @t $op:ident ( $( $args:tt )* ) $( $tail:tt )* ) => ({
-        ($crate::fragment!( $op ( $( $args )* ) ), $crate::fragment_internal!( @t $( $tail )* ))
-    });
-    // Match modifiers
-    ( @t $modif:tt : $( $tail:tt )* ) => ({
-        let (first, tail) = $crate::fragment_internal!( @t $( $tail )* );
-        ($crate::apply_modifier!($modif:first), tail)
-    });
-    // Remove commas between operands
-    ( @t , $( $tail:tt )* ) => ({
-        $crate::fragment_internal!( @t $( $tail )* )
-    });
-    ( @t ) => ({});
-
-    // Fallback to calling `fragment!()`
-    ( $( $tokens:tt )* ) => ({
-        $crate::fragment!($( $tokens )*)
-    });
-}
-
-/// Macro to write descriptor fragments with code
-///
-/// This macro will be expanded to an object of type `Result<(Miniscript<DescriptorPublicKey, _>, KeyMap, ValidNetworks), DescriptorError>`. It allows writing
-/// fragments of larger descriptors that can be pieced together using `fragment!(thresh_vec(m, ...))`.
-///
-/// The syntax to write macro fragment is the same as documented for the [`descriptor`] macro.
-#[macro_export]
-macro_rules! fragment {
-    // Modifiers
-    ( $modif:tt : $( $tail:tt )* ) => ({
-        let op = $crate::fragment!( $( $tail )* );
-        $crate::apply_modifier!($modif:op)
-    });
-
-    // Miniscript
-    ( true ) => ({
-        $crate::impl_leaf_opcode!(True)
-    });
-    ( false ) => ({
-        $crate::impl_leaf_opcode!(False)
-    });
-    ( pk_k ( $key:expr ) ) => ({
-        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
-        $crate::keys::make_pk($key, &secp)
-    });
-    ( pk ( $key:expr ) ) => ({
-        $crate::fragment!(c:pk_k ( $key ))
-    });
-    ( pk_h ( $key:expr ) ) => ({
-        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
-        $crate::keys::make_pkh($key, &secp)
-    });
-    ( after ( $value:expr ) ) => ({
-        $crate::impl_leaf_opcode_value!(After, $crate::miniscript::AbsLockTime::from_consensus($value))
-    });
-    ( older ( $value:expr ) ) => ({
-        $crate::impl_leaf_opcode_value!(Older, $crate::bitcoin::Sequence($value)) // TODO!!
-    });
-    ( sha256 ( $hash:expr ) ) => ({
-        $crate::impl_leaf_opcode_value!(Sha256, $hash)
-    });
-    ( hash256 ( $hash:expr ) ) => ({
-        $crate::impl_leaf_opcode_value!(Hash256, $hash)
-    });
-    ( ripemd160 ( $hash:expr ) ) => ({
-        $crate::impl_leaf_opcode_value!(Ripemd160, $hash)
-    });
-    ( hash160 ( $hash:expr ) ) => ({
-        $crate::impl_leaf_opcode_value!(Hash160, $hash)
-    });
-    ( and_v ( $( $inner:tt )* ) ) => ({
-        $crate::impl_node_opcode_two!(AndV, $( $inner )*)
-    });
-    ( and_b ( $( $inner:tt )* ) ) => ({
-        $crate::impl_node_opcode_two!(AndB, $( $inner )*)
-    });
-    ( and_or ( $( $inner:tt )* ) ) => ({
-        $crate::impl_node_opcode_three!(AndOr, $( $inner )*)
-    });
-    ( andor ( $( $inner:tt )* ) ) => ({
-        $crate::impl_node_opcode_three!(AndOr, $( $inner )*)
-    });
-    ( or_b ( $( $inner:tt )* ) ) => ({
-        $crate::impl_node_opcode_two!(OrB, $( $inner )*)
-    });
-    ( or_d ( $( $inner:tt )* ) ) => ({
-        $crate::impl_node_opcode_two!(OrD, $( $inner )*)
-    });
-    ( or_c ( $( $inner:tt )* ) ) => ({
-        $crate::impl_node_opcode_two!(OrC, $( $inner )*)
-    });
-    ( or_i ( $( $inner:tt )* ) ) => ({
-        $crate::impl_node_opcode_two!(OrI, $( $inner )*)
-    });
-    ( thresh_vec ( $thresh:expr, $items:expr ) ) => ({
-        use $crate::miniscript::descriptor::KeyMap;
-
-        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());
-            let net_acc = $crate::keys::merge_networks(&net_acc, &net);
-
-            (keys_acc, net_acc)
-        });
-
-        $crate::impl_leaf_opcode_value_two!(Thresh, $thresh, items)
-            .map(|(minisc, _, _)| (minisc, key_maps, valid_networks))
-    });
-    ( thresh ( $thresh:expr, $( $inner:tt )* ) ) => ({
-        let items = $crate::fragment_internal!( @v $( $inner )* );
-
-        items.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
-            .and_then(|items| $crate::fragment!(thresh_vec($thresh, items)))
-    });
-    ( multi_vec ( $thresh:expr, $keys:expr ) ) => ({
-        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
-
-        $crate::keys::make_multi($thresh, $crate::miniscript::Terminal::Multi, $keys, &secp)
-    });
-    ( multi ( $thresh:expr $(, $key:expr )+ ) ) => ({
-        $crate::group_multi_keys!( $( $key ),* )
-            .and_then(|keys| $crate::fragment!( multi_vec ( $thresh, keys ) ))
-    });
-    ( multi_a_vec ( $thresh:expr, $keys:expr ) ) => ({
-        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
-
-        $crate::keys::make_multi($thresh, $crate::miniscript::Terminal::MultiA, $keys, &secp)
-    });
-    ( multi_a ( $thresh:expr $(, $key:expr )+ ) ) => ({
-        $crate::group_multi_keys!( $( $key ),* )
-            .and_then(|keys| $crate::fragment!( multi_a_vec ( $thresh, keys ) ))
-    });
-
-    // `sortedmulti()` is handled separately
-    ( sortedmulti ( $( $inner:tt )* ) ) => ({
-        compile_error!("`sortedmulti` can only be used as the root operand of a descriptor");
-    });
-    ( sortedmulti_vec ( $( $inner:tt )* ) ) => ({
-        compile_error!("`sortedmulti_vec` can only be used as the root operand of a descriptor");
-    });
-}
-
-#[cfg(test)]
-mod test {
-    use alloc::string::ToString;
-    use bitcoin::secp256k1::Secp256k1;
-    use miniscript::descriptor::{DescriptorPublicKey, KeyMap};
-    use miniscript::{Descriptor, Legacy, Segwitv0};
-
-    use core::str::FromStr;
-
-    use crate::descriptor::{DescriptorError, DescriptorMeta};
-    use crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
-    use bitcoin::bip32;
-    use bitcoin::Network::{Bitcoin, Regtest, Signet, Testnet};
-    use bitcoin::PrivateKey;
-
-    // test the descriptor!() macro
-
-    // verify descriptor generates expected script(s) (if bare or pk) or address(es)
-    fn check(
-        desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>,
-        is_witness: bool,
-        is_fixed: bool,
-        expected: &[&str],
-    ) {
-        let (desc, _key_map, _networks) = desc.unwrap();
-        assert_eq!(desc.is_witness(), is_witness);
-        assert_eq!(!desc.has_wildcard(), is_fixed);
-        for i in 0..expected.len() {
-            let child_desc = desc
-                .at_derivation_index(i as u32)
-                .expect("i is not hardened");
-            let address = child_desc.address(Regtest);
-            if let Ok(address) = address {
-                assert_eq!(address.to_string(), *expected.get(i).unwrap());
-            } else {
-                let script = child_desc.script_pubkey();
-                assert_eq!(script.to_hex_string(), *expected.get(i).unwrap());
-            }
-        }
-    }
-
-    // - at least one of each "type" of operator; i.e. one modifier, one leaf_opcode, one leaf_opcode_value, etc.
-    // - mixing up key types that implement IntoDescriptorKey in multi() or thresh()
-
-    // expected script for pk and bare manually created
-    // expected addresses created with `bitcoin-cli getdescriptorinfo` (for hash) and `bitcoin-cli deriveaddresses`
-
-    #[test]
-    fn test_fixed_legacy_descriptors() {
-        let pubkey1 = bitcoin::PublicKey::from_str(
-            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
-        )
-        .unwrap();
-        let pubkey2 = bitcoin::PublicKey::from_str(
-            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
-        )
-        .unwrap();
-
-        check(
-            descriptor!(bare(multi(1,pubkey1,pubkey2))),
-            false,
-            true,
-            &["512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af52ae"],
-        );
-        check(
-            descriptor!(pk(pubkey1)),
-            false,
-            true,
-            &["2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"],
-        );
-        check(
-            descriptor!(pkh(pubkey1)),
-            false,
-            true,
-            &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
-        );
-        check(
-            descriptor!(sh(multi(1, pubkey1, pubkey2))),
-            false,
-            true,
-            &["2MymURoV1bzuMnWMGiXzyomDkeuxXY7Suey"],
-        );
-    }
-
-    #[test]
-    fn test_fixed_segwitv0_descriptors() {
-        let pubkey1 = bitcoin::PublicKey::from_str(
-            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
-        )
-        .unwrap();
-        let pubkey2 = bitcoin::PublicKey::from_str(
-            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
-        )
-        .unwrap();
-
-        check(
-            descriptor!(wpkh(pubkey1)),
-            true,
-            true,
-            &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
-        );
-        check(
-            descriptor!(sh(wpkh(pubkey1))),
-            true,
-            true,
-            &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
-        );
-        check(
-            descriptor!(wsh(multi(1, pubkey1, pubkey2))),
-            true,
-            true,
-            &["bcrt1qgw8jvv2hsrvjfa6q66rk6har7d32lrqm5unnf5cl63q9phxfvgps5fyfqe"],
-        );
-        check(
-            descriptor!(sh(wsh(multi(1, pubkey1, pubkey2)))),
-            true,
-            true,
-            &["2NCidRJysy7apkmE6JF5mLLaJFkrN3Ub9iy"],
-        );
-    }
-
-    #[test]
-    fn test_fixed_threeop_descriptors() {
-        let redeem_key = bitcoin::PublicKey::from_str(
-            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
-        )
-        .unwrap();
-        let move_key = bitcoin::PublicKey::from_str(
-            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
-        )
-        .unwrap();
-
-        check(
-            descriptor!(sh(wsh(and_or(pk(redeem_key), older(1000), pk(move_key))))),
-            true,
-            true,
-            &["2MypGwr5eQWAWWJtiJgUEToVxc4zuokjQRe"],
-        );
-    }
-
-    #[test]
-    fn test_bip32_legacy_descriptors() {
-        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-
-        let path = bip32::DerivationPath::from_str("m/0").unwrap();
-        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
-        check(
-            descriptor!(pk(desc_key)),
-            false,
-            false,
-            &[
-                "2102363ad03c10024e1b597a5b01b9982807fb638e00b06f3b2d4a89707de3b93c37ac",
-                "2102063a21fd780df370ed2fc8c4b86aa5ea642630609c203009df631feb7b480dd2ac",
-                "2102ba2685ad1fa5891cb100f1656b2ce3801822ccb9bac0336734a6f8c1b93ebbc0ac",
-            ],
-        );
-
-        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
-        check(
-            descriptor!(pkh(desc_key)),
-            false,
-            false,
-            &[
-                "muvBdsVpJxpFuTHMKA47htJPdCvdt4F9DP",
-                "mxQSHK7DL2t1DN3xFxov1janCoXSSkrSPj",
-                "mfz43r15GiWo4nizmyzMNubsnkDpByFFAn",
-            ],
-        );
-
-        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
-        let desc_key1 = (xprv, path).into_descriptor_key().unwrap();
-        let desc_key2 = (xprv, path2).into_descriptor_key().unwrap();
-
-        check(
-            descriptor!(sh(multi(1, desc_key1, desc_key2))),
-            false,
-            false,
-            &[
-                "2MtMDXsfwefZkEEhVViEPidvcKRUtJamJJ8",
-                "2MwAUZ1NYyWjhVvGTethFL6n7nZhS8WE6At",
-                "2MuT6Bj66HLwZd7s4SoD8XbK4GwriKEA6Gr",
-            ],
-        );
-    }
-
-    #[test]
-    fn test_bip32_segwitv0_descriptors() {
-        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-
-        let path = bip32::DerivationPath::from_str("m/0").unwrap();
-        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
-        check(
-            descriptor!(wpkh(desc_key)),
-            true,
-            false,
-            &[
-                "bcrt1qnhm8w9fhc8cxzgqsmqdf9fyjccyvc0gltnymu0",
-                "bcrt1qhylfd55rn75w9fj06zspctad5w4hz33rf0ttad",
-                "bcrt1qq5sq3a6k9av9d8cne0k9wcldy4nqey5yt6889r",
-            ],
-        );
-
-        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
-        check(
-            descriptor!(sh(wpkh(desc_key))),
-            true,
-            false,
-            &[
-                "2MxvjQCaLqZ5QxZ7XotZDQ63hZw3NPss763",
-                "2NDUoevN4QMzhvHDMGhKuiT2fN9HXbFRMwn",
-                "2NF4BEAY2jF1Fu8vqfN3NVKoFtom77pUxrx",
-            ],
-        );
-
-        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
-        let desc_key1 = (xprv, path.clone()).into_descriptor_key().unwrap();
-        let desc_key2 = (xprv, path2.clone()).into_descriptor_key().unwrap();
-        check(
-            descriptor!(wsh(multi(1, desc_key1, desc_key2))),
-            true,
-            false,
-            &[
-                "bcrt1qfxv8mxmlv5sz8q2mnuyaqdfe9jr4vvmx0csjhn092p6f4qfygfkq2hng49",
-                "bcrt1qerj85g243e6jlcdxpmn9spk0gefcwvu7nw7ee059d5ydzpdhkm2qwfkf5k",
-                "bcrt1qxkl2qss3k58q9ktc8e89pwr4gnptfpw4hju4xstxcjc0hkcae3jstluty7",
-            ],
-        );
-
-        let desc_key1 = (xprv, path).into_descriptor_key().unwrap();
-        let desc_key2 = (xprv, path2).into_descriptor_key().unwrap();
-        check(
-            descriptor!(sh(wsh(multi(1, desc_key1, desc_key2)))),
-            true,
-            false,
-            &[
-                "2NFCtXvx9q4ci2kvKub17iSTgvRXGctCGhz",
-                "2NB2PrFPv5NxWCpygas8tPrGJG2ZFgeuwJw",
-                "2N79ZAGo5cMi5Jt7Wo9L5YmF5GkEw7sjWdC",
-            ],
-        );
-    }
-
-    #[test]
-    fn test_dsl_sortedmulti() {
-        let key_1 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-        let path_1 = bip32::DerivationPath::from_str("m/0").unwrap();
-
-        let key_2 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
-        let path_2 = bip32::DerivationPath::from_str("m/1").unwrap();
-
-        let desc_key1 = (key_1, path_1);
-        let desc_key2 = (key_2, path_2);
-
-        check(
-            descriptor!(sh(sortedmulti(1, desc_key1.clone(), desc_key2.clone()))),
-            false,
-            false,
-            &[
-                "2MsxzPEJDBzpGffJXPaDpfXZAUNnZhaMh2N",
-                "2My3x3DLPK3UbGWGpxrXr1RnbD8MNC4FpgS",
-                "2NByEuiQT7YLqHCTNxL5KwYjvtuCYcXNBSC",
-                "2N1TGbP81kj2VUKTSWgrwxoMfuWjvfUdyu7",
-                "2N3Bomq2fpAcLRNfZnD3bCWK9quan28CxCR",
-                "2N9nrZaEzEFDqEAU9RPvDnXGT6AVwBDKAQb",
-            ],
-        );
-
-        check(
-            descriptor!(sh(wsh(sortedmulti(
-                1,
-                desc_key1.clone(),
-                desc_key2.clone()
-            )))),
-            true,
-            false,
-            &[
-                "2NCogc5YyM4N6ruv1hUa7WLMW1BPeCK7N9B",
-                "2N6mkSAKi1V2oaBXby7XHdvBMKEDRQcFpNe",
-                "2NFmTSttm9v6bXeoWaBvpMcgfPQcZhNn3Eh",
-                "2Mvib87RBPUHXNEpX5S5Kv1qqrhBfgBGsJM",
-                "2MtMv5mcK2EjcLsH8Txpx2JxLLzHr4ttczL",
-                "2MsWCB56rb4T6yPv8QudZGHERTwNgesE4f6",
-            ],
-        );
-
-        check(
-            descriptor!(wsh(sortedmulti_vec(1, vec![desc_key1, desc_key2]))),
-            true,
-            false,
-            &[
-                "bcrt1qcvq0lg8q7a47ytrd7zk5y7uls7mulrenjgvflwylpppgwf8029es4vhpnj",
-                "bcrt1q80yn8sdt6l7pjvkz25lglyaqctlmsq9ugk80rmxt8yu0npdsj97sc7l4de",
-                "bcrt1qrvf6024v9s50qhffe3t2fr2q9ckdhx2g6jz32chm2pp24ymgtr5qfrdmct",
-                "bcrt1q6srfmra0ynypym35c7jvsxt2u4yrugeajq95kg2ps7lk6h2gaunsq9lzxn",
-                "bcrt1qhl8rrzzcdpu7tcup3lcg7tge52sqvwy5fcv4k78v6kxtwmqf3v6qpvyjza",
-                "bcrt1ql2elz9mhm9ll27ddpewhxs732xyl2fk2kpkqz9gdyh33wgcun4vstrd49k",
-            ],
-        );
-    }
-
-    // - verify the valid_networks returned is correctly computed based on the keys present in the descriptor
-    #[test]
-    fn test_valid_networks() {
-        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-        let path = bip32::DerivationPath::from_str("m/0").unwrap();
-        let desc_key = (xprv, path).into_descriptor_key().unwrap();
-
-        let (_desc, _key_map, valid_networks) = descriptor!(pkh(desc_key)).unwrap();
-        assert_eq!(
-            valid_networks,
-            [Testnet, Regtest, Signet].iter().cloned().collect()
-        );
-
-        let xprv = bip32::Xpriv::from_str("xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").unwrap();
-        let path = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
-        let desc_key = (xprv, path).into_descriptor_key().unwrap();
-
-        let (_desc, _key_map, valid_networks) = descriptor!(wpkh(desc_key)).unwrap();
-        assert_eq!(valid_networks, [Bitcoin].iter().cloned().collect());
-    }
-
-    // - verify the key_maps are correctly merged together
-    #[test]
-    fn test_key_maps_merged() {
-        let secp = Secp256k1::new();
-
-        let xprv1 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-        let path1 = bip32::DerivationPath::from_str("m/0").unwrap();
-        let desc_key1 = (xprv1, path1.clone()).into_descriptor_key().unwrap();
-
-        let xprv2 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
-        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
-        let desc_key2 = (xprv2, path2.clone()).into_descriptor_key().unwrap();
-
-        let xprv3 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf").unwrap();
-        let path3 = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
-        let desc_key3 = (xprv3, path3.clone()).into_descriptor_key().unwrap();
-
-        let (_desc, key_map, _valid_networks) =
-            descriptor!(sh(wsh(multi(2, desc_key1, desc_key2, desc_key3)))).unwrap();
-        assert_eq!(key_map.len(), 3);
-
-        let desc_key1: DescriptorKey<Segwitv0> = (xprv1, path1).into_descriptor_key().unwrap();
-        let desc_key2: DescriptorKey<Segwitv0> = (xprv2, path2).into_descriptor_key().unwrap();
-        let desc_key3: DescriptorKey<Segwitv0> = (xprv3, path3).into_descriptor_key().unwrap();
-
-        let (key1, _key_map, _valid_networks) = desc_key1.extract(&secp).unwrap();
-        let (key2, _key_map, _valid_networks) = desc_key2.extract(&secp).unwrap();
-        let (key3, _key_map, _valid_networks) = desc_key3.extract(&secp).unwrap();
-        assert_eq!(key_map.get(&key1).unwrap().to_string(), "tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy/0/*");
-        assert_eq!(key_map.get(&key2).unwrap().to_string(), "tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF/2147483647'/0/*");
-        assert_eq!(key_map.get(&key3).unwrap().to_string(), "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf/10/20/30/40/*");
-    }
-
-    // - verify the ScriptContext is correctly validated (i.e. passing a type that only impl IntoDescriptorKey<Segwitv0> to a pkh() descriptor should throw a compilation error
-    #[test]
-    fn test_script_context_validation() {
-        // this compiles
-        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-        let path = bip32::DerivationPath::from_str("m/0").unwrap();
-        let desc_key: DescriptorKey<Legacy> = (xprv, path).into_descriptor_key().unwrap();
-
-        let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
-        assert_eq!(desc.to_string(), "pkh(tpubD6NzVbkrYhZ4WR7a4vY1VT3khMJMeAxVsfq9TBJyJWrNk247zCJtV7AWf6UJP7rAVsn8NNKdJi3gFyKPTmWZS9iukb91xbn2HbFSMQm2igY/0/*)#yrnz9pp2");
-
-        // as expected this does not compile due to invalid context
-        //let desc_key:DescriptorKey<Segwitv0> = (xprv, path.clone()).into_descriptor_key().unwrap();
-        //let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
-    }
-
-    #[test]
-    fn test_dsl_modifiers() {
-        let private_key =
-            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
-        let (descriptor, _, _) =
-            descriptor!(wsh(thresh(2,n:d:v:older(1),s:pk(private_key),s:pk(private_key)))).unwrap();
-
-        assert_eq!(descriptor.to_string(), "wsh(thresh(2,ndv:older(1),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)))#zzk3ux8g")
-    }
-
-    #[test]
-    #[should_panic(expected = "Miniscript(ContextError(UncompressedKeysNotAllowed))")]
-    fn test_dsl_miniscript_checks() {
-        let mut uncompressed_pk =
-            PrivateKey::from_wif("L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6").unwrap();
-        uncompressed_pk.compressed = false;
-
-        descriptor!(wsh(v: pk(uncompressed_pk))).unwrap();
-    }
-
-    #[test]
-    fn test_dsl_tr_only_key() {
-        let private_key =
-            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
-        let (descriptor, _, _) = descriptor!(tr(private_key)).unwrap();
-
-        assert_eq!(
-            descriptor.to_string(),
-            "tr(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)#heq9m95v"
-        )
-    }
-
-    #[test]
-    fn test_dsl_tr_simple_tree() {
-        let private_key =
-            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
-        let (descriptor, _, _) =
-            descriptor!(tr(private_key, { pk(private_key), pk(private_key) })).unwrap();
-
-        assert_eq!(descriptor.to_string(), "tr(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c,{pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)})#xy5fjw6d")
-    }
-
-    #[test]
-    fn test_dsl_tr_single_leaf() {
-        let private_key =
-            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
-        let (descriptor, _, _) = descriptor!(tr(private_key, pk(private_key))).unwrap();
-
-        assert_eq!(descriptor.to_string(), "tr(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c,pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c))#lzl2vmc7")
-    }
-}
-
-
\ No newline at end of file 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 deleted file mode 100644 index b3711a31fe..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/error.rs.html +++ /dev/null @@ -1,249 +0,0 @@ -error.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
-
// 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.
-
-//! Descriptor errors
-use core::fmt;
-
-/// Errors related to the parsing and usage of descriptors
-#[derive(Debug)]
-pub enum Error {
-    /// Invalid HD Key path, such as having a wildcard but a length != 1
-    InvalidHdKeyPath,
-    /// The provided descriptor doesn't match its checksum
-    InvalidDescriptorChecksum,
-    /// The descriptor contains hardened derivation steps on public extended keys
-    HardenedDerivationXpub,
-    /// The descriptor contains multipath keys
-    MultiPath,
-
-    /// Error thrown while working with [`keys`](crate::keys)
-    Key(crate::keys::KeyError),
-    /// Error while extracting and manipulating policies
-    Policy(crate::descriptor::policy::PolicyError),
-
-    /// Invalid byte found in the descriptor checksum
-    InvalidDescriptorCharacter(u8),
-
-    /// BIP32 error
-    Bip32(bitcoin::bip32::Error),
-    /// Error during base58 decoding
-    Base58(bitcoin::base58::Error),
-    /// Key-related error
-    Pk(bitcoin::key::Error),
-    /// Miniscript error
-    Miniscript(miniscript::Error),
-    /// Hex decoding error
-    Hex(bitcoin::hex::HexToBytesError),
-}
-
-impl From<crate::keys::KeyError> for Error {
-    fn from(key_error: crate::keys::KeyError) -> Error {
-        match key_error {
-            crate::keys::KeyError::Miniscript(inner) => Error::Miniscript(inner),
-            crate::keys::KeyError::Bip32(inner) => Error::Bip32(inner),
-            e => Error::Key(e),
-        }
-    }
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::InvalidHdKeyPath => write!(f, "Invalid HD key path"),
-            Self::InvalidDescriptorChecksum => {
-                write!(f, "The provided descriptor doesn't match its checksum")
-            }
-            Self::HardenedDerivationXpub => write!(
-                f,
-                "The descriptor contains hardened derivation steps on public extended keys"
-            ),
-            Self::MultiPath => write!(
-                f,
-                "The descriptor contains multipath keys, which are not supported yet"
-            ),
-            Self::Key(err) => write!(f, "Key error: {}", err),
-            Self::Policy(err) => write!(f, "Policy error: {}", err),
-            Self::InvalidDescriptorCharacter(char) => {
-                write!(f, "Invalid descriptor character: {}", char)
-            }
-            Self::Bip32(err) => write!(f, "BIP32 error: {}", err),
-            Self::Base58(err) => write!(f, "Base58 error: {}", err),
-            Self::Pk(err) => write!(f, "Key-related error: {}", err),
-            Self::Miniscript(err) => write!(f, "Miniscript error: {}", err),
-            Self::Hex(err) => write!(f, "Hex decoding error: {}", err),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for Error {}
-
-impl From<bitcoin::bip32::Error> for Error {
-    fn from(err: bitcoin::bip32::Error) -> Self {
-        Error::Bip32(err)
-    }
-}
-
-impl From<bitcoin::base58::Error> for Error {
-    fn from(err: bitcoin::base58::Error) -> Self {
-        Error::Base58(err)
-    }
-}
-
-impl From<bitcoin::key::Error> for Error {
-    fn from(err: bitcoin::key::Error) -> Self {
-        Error::Pk(err)
-    }
-}
-
-impl From<miniscript::Error> for Error {
-    fn from(err: miniscript::Error) -> Self {
-        Error::Miniscript(err)
-    }
-}
-
-impl From<bitcoin::hex::HexToBytesError> for Error {
-    fn from(err: bitcoin::hex::HexToBytesError) -> Self {
-        Error::Hex(err)
-    }
-}
-
-impl From<crate::descriptor::policy::PolicyError> for Error {
-    fn from(err: crate::descriptor::policy::PolicyError) -> Self {
-        Error::Policy(err)
-    }
-}
-
-
\ No newline at end of file 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 deleted file mode 100644 index 53e32d36c0..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/mod.rs.html +++ /dev/null @@ -1,1803 +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
-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
-
// 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.
-
-//! Descriptors
-//!
-//! This module contains generic utilities to work with descriptors, plus some re-exported types
-//! from [`miniscript`].
-
-use crate::collections::BTreeMap;
-use alloc::string::String;
-use alloc::vec::Vec;
-
-use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, KeySource, Xpub};
-use bitcoin::{key::XOnlyPublicKey, secp256k1, PublicKey};
-use bitcoin::{psbt, taproot};
-use bitcoin::{Network, TxOut};
-
-use miniscript::descriptor::{
-    DefiniteDescriptorKey, DescriptorMultiXKey, DescriptorSecretKey, DescriptorType,
-    DescriptorXKey, InnerXKey, KeyMap, SinglePubKey, Wildcard,
-};
-pub use miniscript::{
-    Descriptor, DescriptorPublicKey, Legacy, Miniscript, ScriptContext, Segwitv0,
-};
-use miniscript::{ForEachKey, MiniscriptKey, TranslatePk};
-
-use crate::descriptor::policy::BuildSatisfaction;
-
-pub mod checksum;
-#[doc(hidden)]
-pub mod dsl;
-pub mod error;
-pub mod policy;
-pub mod template;
-
-pub use self::checksum::calc_checksum;
-use self::checksum::calc_checksum_bytes;
-pub use self::error::Error as DescriptorError;
-pub use self::policy::Policy;
-use self::template::DescriptorTemplateOut;
-use crate::keys::{IntoDescriptorKey, KeyError};
-use crate::wallet::signer::SignersContainer;
-use crate::wallet::utils::SecpCtx;
-
-/// Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]
-pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
-
-/// Alias for a [`Descriptor`] that contains extended **derived** keys
-pub type DerivedDescriptor = Descriptor<DefiniteDescriptorKey>;
-
-/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
-/// [`psbt::Output`]
-///
-/// [`psbt::Input`]: bitcoin::psbt::Input
-/// [`psbt::Output`]: bitcoin::psbt::Output
-pub type HdKeyPaths = BTreeMap<secp256k1::PublicKey, KeySource>;
-
-/// Alias for the type of maps that represent taproot key origins in a [`psbt::Input`] or
-/// [`psbt::Output`]
-///
-/// [`psbt::Input`]: bitcoin::psbt::Input
-/// [`psbt::Output`]: bitcoin::psbt::Output
-pub type TapKeyOrigins = BTreeMap<XOnlyPublicKey, (Vec<taproot::TapLeafHash>, KeySource)>;
-
-/// Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]
-pub trait IntoWalletDescriptor {
-    /// Convert to wallet descriptor
-    fn into_wallet_descriptor(
-        self,
-        secp: &SecpCtx,
-        network: Network,
-    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError>;
-}
-
-impl IntoWalletDescriptor for &str {
-    fn into_wallet_descriptor(
-        self,
-        secp: &SecpCtx,
-        network: Network,
-    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
-        let descriptor = match self.split_once('#') {
-            Some((desc, original_checksum)) => {
-                let checksum = calc_checksum_bytes(desc)?;
-                if original_checksum.as_bytes() != checksum {
-                    return Err(DescriptorError::InvalidDescriptorChecksum);
-                }
-                desc
-            }
-            None => self,
-        };
-
-        ExtendedDescriptor::parse_descriptor(secp, descriptor)?
-            .into_wallet_descriptor(secp, network)
-    }
-}
-
-impl IntoWalletDescriptor for &String {
-    fn into_wallet_descriptor(
-        self,
-        secp: &SecpCtx,
-        network: Network,
-    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
-        self.as_str().into_wallet_descriptor(secp, network)
-    }
-}
-
-impl IntoWalletDescriptor for ExtendedDescriptor {
-    fn into_wallet_descriptor(
-        self,
-        secp: &SecpCtx,
-        network: Network,
-    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
-        (self, KeyMap::default()).into_wallet_descriptor(secp, network)
-    }
-}
-
-impl IntoWalletDescriptor for (ExtendedDescriptor, KeyMap) {
-    fn into_wallet_descriptor(
-        self,
-        secp: &SecpCtx,
-        network: Network,
-    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
-        use crate::keys::DescriptorKey;
-
-        struct Translator<'s, 'd> {
-            secp: &'s SecpCtx,
-            descriptor: &'d ExtendedDescriptor,
-            network: Network,
-        }
-
-        impl<'s, 'd> miniscript::Translator<DescriptorPublicKey, String, DescriptorError>
-            for Translator<'s, 'd>
-        {
-            fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, DescriptorError> {
-                let secp = &self.secp;
-
-                let (_, _, networks) = if self.descriptor.is_taproot() {
-                    let descriptor_key: DescriptorKey<miniscript::Tap> =
-                        pk.clone().into_descriptor_key()?;
-                    descriptor_key.extract(secp)?
-                } else if self.descriptor.is_witness() {
-                    let descriptor_key: DescriptorKey<miniscript::Segwitv0> =
-                        pk.clone().into_descriptor_key()?;
-                    descriptor_key.extract(secp)?
-                } else {
-                    let descriptor_key: DescriptorKey<miniscript::Legacy> =
-                        pk.clone().into_descriptor_key()?;
-                    descriptor_key.extract(secp)?
-                };
-
-                if networks.contains(&self.network) {
-                    Ok(Default::default())
-                } else {
-                    Err(DescriptorError::Key(KeyError::InvalidNetwork))
-                }
-            }
-            fn sha256(
-                &mut self,
-                _sha256: &<DescriptorPublicKey as MiniscriptKey>::Sha256,
-            ) -> Result<String, DescriptorError> {
-                Ok(Default::default())
-            }
-            fn hash256(
-                &mut self,
-                _hash256: &<DescriptorPublicKey as MiniscriptKey>::Hash256,
-            ) -> Result<String, DescriptorError> {
-                Ok(Default::default())
-            }
-            fn ripemd160(
-                &mut self,
-                _ripemd160: &<DescriptorPublicKey as MiniscriptKey>::Ripemd160,
-            ) -> Result<String, DescriptorError> {
-                Ok(Default::default())
-            }
-            fn hash160(
-                &mut self,
-                _hash160: &<DescriptorPublicKey as MiniscriptKey>::Hash160,
-            ) -> Result<String, DescriptorError> {
-                Ok(Default::default())
-            }
-        }
-
-        // check the network for the keys
-        use miniscript::TranslateErr;
-        match self.0.translate_pk(&mut Translator {
-            secp,
-            network,
-            descriptor: &self.0,
-        }) {
-            Ok(_) => {}
-            Err(TranslateErr::TranslatorErr(e)) => return Err(e),
-            Err(TranslateErr::OuterError(e)) => return Err(e.into()),
-        }
-
-        Ok(self)
-    }
-}
-
-impl IntoWalletDescriptor for DescriptorTemplateOut {
-    fn into_wallet_descriptor(
-        self,
-        _secp: &SecpCtx,
-        network: Network,
-    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
-        struct Translator {
-            network: Network,
-        }
-
-        impl miniscript::Translator<DescriptorPublicKey, DescriptorPublicKey, DescriptorError>
-            for Translator
-        {
-            fn pk(
-                &mut self,
-                pk: &DescriptorPublicKey,
-            ) -> Result<DescriptorPublicKey, DescriptorError> {
-                // workaround for xpubs generated by other key types, like bip39: since when the
-                // conversion is made one network has to be chosen, what we generally choose
-                // "mainnet", but then override the set of valid networks to specify that all of
-                // them are valid. here we reset the network to make sure the wallet struct gets a
-                // descriptor with the right network everywhere.
-                let pk = match pk {
-                    DescriptorPublicKey::XPub(ref xpub) => {
-                        let mut xpub = xpub.clone();
-                        xpub.xkey.network = self.network;
-
-                        DescriptorPublicKey::XPub(xpub)
-                    }
-                    other => other.clone(),
-                };
-
-                Ok(pk)
-            }
-            miniscript::translate_hash_clone!(
-                DescriptorPublicKey,
-                DescriptorPublicKey,
-                DescriptorError
-            );
-        }
-
-        let (desc, keymap, networks) = self;
-
-        if !networks.contains(&network) {
-            return Err(DescriptorError::Key(KeyError::InvalidNetwork));
-        }
-
-        // fixup the network for keys that need it in the descriptor
-        use miniscript::TranslateErr;
-        let translated = match desc.translate_pk(&mut Translator { network }) {
-            Ok(descriptor) => descriptor,
-            Err(TranslateErr::TranslatorErr(e)) => return Err(e),
-            Err(TranslateErr::OuterError(e)) => return Err(e.into()),
-        };
-        // ...and in the key map
-        let fixed_keymap = keymap
-            .into_iter()
-            .map(|(mut k, mut v)| {
-                match (&mut k, &mut v) {
-                    (DescriptorPublicKey::XPub(xpub), DescriptorSecretKey::XPrv(xprv)) => {
-                        xpub.xkey.network = network;
-                        xprv.xkey.network = network;
-                    }
-                    (_, DescriptorSecretKey::Single(key)) => {
-                        key.key.network = network;
-                    }
-                    _ => {}
-                }
-
-                (k, v)
-            })
-            .collect();
-
-        Ok((translated, fixed_keymap))
-    }
-}
-
-/// Wrapper for `IntoWalletDescriptor` that performs additional checks on the keys contained in the
-/// descriptor
-pub(crate) fn into_wallet_descriptor_checked<T: IntoWalletDescriptor>(
-    inner: T,
-    secp: &SecpCtx,
-    network: Network,
-) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
-    let (descriptor, keymap) = inner.into_wallet_descriptor(secp, network)?;
-
-    // Ensure the keys don't contain any hardened derivation steps or hardened wildcards
-    let descriptor_contains_hardened_steps = descriptor.for_any_key(|k| {
-        if let DescriptorPublicKey::XPub(DescriptorXKey {
-            derivation_path,
-            wildcard,
-            ..
-        }) = k
-        {
-            return *wildcard == Wildcard::Hardened
-                || derivation_path.into_iter().any(ChildNumber::is_hardened);
-        }
-
-        false
-    });
-    if descriptor_contains_hardened_steps {
-        return Err(DescriptorError::HardenedDerivationXpub);
-    }
-
-    if descriptor.is_multipath() {
-        return Err(DescriptorError::MultiPath);
-    }
-
-    // Run miniscript's sanity check, which will look for duplicated keys and other potential
-    // issues
-    descriptor.sanity_check()?;
-
-    Ok((descriptor, keymap))
-}
-
-#[doc(hidden)]
-/// Used internally mainly by the `descriptor!()` and `fragment!()` macros
-pub trait CheckMiniscript<Ctx: miniscript::ScriptContext> {
-    fn check_miniscript(&self) -> Result<(), miniscript::Error>;
-}
-
-impl<Ctx: miniscript::ScriptContext, Pk: miniscript::MiniscriptKey> CheckMiniscript<Ctx>
-    for miniscript::Miniscript<Pk, Ctx>
-{
-    fn check_miniscript(&self) -> Result<(), miniscript::Error> {
-        Ctx::check_global_validity(self)?;
-
-        Ok(())
-    }
-}
-
-/// Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]
-pub trait ExtractPolicy {
-    /// Extract the spending [`policy`]
-    fn extract_policy(
-        &self,
-        signers: &SignersContainer,
-        psbt: BuildSatisfaction,
-        secp: &SecpCtx,
-    ) -> Result<Option<Policy>, DescriptorError>;
-}
-
-pub(crate) trait XKeyUtils {
-    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint;
-}
-
-impl<T> XKeyUtils for DescriptorMultiXKey<T>
-where
-    T: InnerXKey,
-{
-    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint {
-        match self.origin {
-            Some((fingerprint, _)) => fingerprint,
-            None => self.xkey.xkey_fingerprint(secp),
-        }
-    }
-}
-
-impl<T> XKeyUtils for DescriptorXKey<T>
-where
-    T: InnerXKey,
-{
-    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint {
-        match self.origin {
-            Some((fingerprint, _)) => fingerprint,
-            None => self.xkey.xkey_fingerprint(secp),
-        }
-    }
-}
-
-pub(crate) trait DescriptorMeta {
-    fn is_witness(&self) -> bool;
-    fn is_taproot(&self) -> bool;
-    fn get_extended_keys(&self) -> Vec<DescriptorXKey<Xpub>>;
-    fn derive_from_hd_keypaths(
-        &self,
-        hd_keypaths: &HdKeyPaths,
-        secp: &SecpCtx,
-    ) -> Option<DerivedDescriptor>;
-    fn derive_from_tap_key_origins(
-        &self,
-        tap_key_origins: &TapKeyOrigins,
-        secp: &SecpCtx,
-    ) -> Option<DerivedDescriptor>;
-    fn derive_from_psbt_key_origins(
-        &self,
-        key_origins: BTreeMap<Fingerprint, (&DerivationPath, SinglePubKey)>,
-        secp: &SecpCtx,
-    ) -> Option<DerivedDescriptor>;
-    fn derive_from_psbt_input(
-        &self,
-        psbt_input: &psbt::Input,
-        utxo: Option<TxOut>,
-        secp: &SecpCtx,
-    ) -> Option<DerivedDescriptor>;
-}
-
-impl DescriptorMeta for ExtendedDescriptor {
-    fn is_witness(&self) -> bool {
-        matches!(
-            self.desc_type(),
-            DescriptorType::Wpkh
-                | DescriptorType::ShWpkh
-                | DescriptorType::Wsh
-                | DescriptorType::ShWsh
-                | DescriptorType::ShWshSortedMulti
-                | DescriptorType::WshSortedMulti
-        )
-    }
-
-    fn is_taproot(&self) -> bool {
-        self.desc_type() == DescriptorType::Tr
-    }
-
-    fn get_extended_keys(&self) -> Vec<DescriptorXKey<Xpub>> {
-        let mut answer = Vec::new();
-
-        self.for_each_key(|pk| {
-            if let DescriptorPublicKey::XPub(xpub) = pk {
-                answer.push(xpub.clone());
-            }
-
-            true
-        });
-
-        answer
-    }
-
-    fn derive_from_psbt_key_origins(
-        &self,
-        key_origins: BTreeMap<Fingerprint, (&DerivationPath, SinglePubKey)>,
-        secp: &SecpCtx,
-    ) -> Option<DerivedDescriptor> {
-        // Ensure that deriving `xpub` with `path` yields `expected`
-        let verify_key =
-            |xpub: &DescriptorXKey<Xpub>, path: &DerivationPath, expected: &SinglePubKey| {
-                let derived = xpub
-                    .xkey
-                    .derive_pub(secp, path)
-                    .expect("The path should never contain hardened derivation steps")
-                    .public_key;
-
-                match expected {
-                    SinglePubKey::FullKey(pk) if &PublicKey::new(derived) == pk => true,
-                    SinglePubKey::XOnly(pk) if &XOnlyPublicKey::from(derived) == pk => true,
-                    _ => false,
-                }
-            };
-
-        let mut path_found = None;
-
-        // using `for_any_key` should make this stop as soon as we return `true`
-        self.for_any_key(|key| {
-            if let DescriptorPublicKey::XPub(xpub) = key {
-                // Check if the key matches one entry in our `key_origins`. If it does, `matches()` will
-                // return the "prefix" that matched, so we remove that prefix from the full path
-                // found in `key_origins` and save it in `derive_path`. We expect this to be a derivation
-                // path of length 1 if the key is `wildcard` and an empty path otherwise.
-                let root_fingerprint = xpub.root_fingerprint(secp);
-                let derive_path = key_origins
-                    .get_key_value(&root_fingerprint)
-                    .and_then(|(fingerprint, (path, expected))| {
-                        xpub.matches(&(*fingerprint, (*path).clone()), secp)
-                            .zip(Some((path, expected)))
-                    })
-                    .and_then(|(prefix, (full_path, expected))| {
-                        let derive_path = full_path
-                            .into_iter()
-                            .skip(prefix.into_iter().count())
-                            .cloned()
-                            .collect::<DerivationPath>();
-
-                        // `derive_path` only contains the replacement index for the wildcard, if present, or
-                        // an empty path for fixed descriptors. To verify the key we also need the normal steps
-                        // that come before the wildcard, so we take them directly from `xpub` and then append
-                        // the final index
-                        if verify_key(
-                            xpub,
-                            &xpub.derivation_path.extend(derive_path.clone()),
-                            expected,
-                        ) {
-                            Some(derive_path)
-                        } else {
-                            None
-                        }
-                    });
-
-                match derive_path {
-                    Some(path) if xpub.wildcard != Wildcard::None && path.len() == 1 => {
-                        // Ignore hardened wildcards
-                        if let ChildNumber::Normal { index } = path[0] {
-                            path_found = Some(index);
-                            return true;
-                        }
-                    }
-                    Some(path) if xpub.wildcard == Wildcard::None && path.is_empty() => {
-                        path_found = Some(0);
-                        return true;
-                    }
-                    _ => {}
-                }
-            }
-
-            false
-        });
-
-        path_found.map(|path| {
-            self.at_derivation_index(path)
-                .expect("We ignore hardened wildcards")
-        })
-    }
-
-    fn derive_from_hd_keypaths(
-        &self,
-        hd_keypaths: &HdKeyPaths,
-        secp: &SecpCtx,
-    ) -> Option<DerivedDescriptor> {
-        // "Convert" an hd_keypaths map to the format required by `derive_from_psbt_key_origins`
-        let key_origins = hd_keypaths
-            .iter()
-            .map(|(pk, (fingerprint, path))| {
-                (
-                    *fingerprint,
-                    (path, SinglePubKey::FullKey(PublicKey::new(*pk))),
-                )
-            })
-            .collect();
-        self.derive_from_psbt_key_origins(key_origins, secp)
-    }
-
-    fn derive_from_tap_key_origins(
-        &self,
-        tap_key_origins: &TapKeyOrigins,
-        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
-            .iter()
-            .map(|(pk, (_, (fingerprint, path)))| (*fingerprint, (path, SinglePubKey::XOnly(*pk))))
-            .collect();
-        self.derive_from_psbt_key_origins(key_origins, secp)
-    }
-
-    fn derive_from_psbt_input(
-        &self,
-        psbt_input: &psbt::Input,
-        utxo: Option<TxOut>,
-        secp: &SecpCtx,
-    ) -> Option<DerivedDescriptor> {
-        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.bip32_derivation, secp) {
-            return Some(derived);
-        }
-        if let Some(derived) = self.derive_from_tap_key_origins(&psbt_input.tap_key_origins, secp) {
-            return Some(derived);
-        }
-        if self.has_wildcard() {
-            // We can't try to bruteforce the derivation index, exit here
-            return None;
-        }
-
-        let descriptor = self.at_derivation_index(0).expect("0 is not hardened");
-        match descriptor.desc_type() {
-            // TODO: add pk() here
-            DescriptorType::Pkh
-            | DescriptorType::Wpkh
-            | DescriptorType::ShWpkh
-            | DescriptorType::Tr
-                if utxo.is_some()
-                    && descriptor.script_pubkey() == utxo.as_ref().unwrap().script_pubkey =>
-            {
-                Some(descriptor)
-            }
-            DescriptorType::Bare | DescriptorType::Sh | DescriptorType::ShSortedMulti
-                if psbt_input.redeem_script.is_some()
-                    && &descriptor.explicit_script().unwrap()
-                        == psbt_input.redeem_script.as_ref().unwrap() =>
-            {
-                Some(descriptor)
-            }
-            DescriptorType::Wsh
-            | DescriptorType::ShWsh
-            | DescriptorType::ShWshSortedMulti
-            | DescriptorType::WshSortedMulti
-                if psbt_input.witness_script.is_some()
-                    && &descriptor.explicit_script().unwrap()
-                        == psbt_input.witness_script.as_ref().unwrap() =>
-            {
-                Some(descriptor)
-            }
-            _ => None,
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use alloc::string::ToString;
-    use core::str::FromStr;
-
-    use assert_matches::assert_matches;
-    use bitcoin::hex::FromHex;
-    use bitcoin::secp256k1::Secp256k1;
-    use bitcoin::ScriptBuf;
-    use bitcoin::{bip32, Psbt};
-
-    use super::*;
-    use crate::psbt::PsbtUtils;
-
-    #[test]
-    fn test_derive_from_psbt_input_wpkh_wif() {
-        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
-            "wpkh(02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737)",
-        )
-        .unwrap();
-        let psbt = Psbt::deserialize(
-            &Vec::<u8>::from_hex(
-                "70736274ff010052010000000162307be8e431fbaff807cdf9cdc3fde44d7402\
-                 11bc8342c31ffd6ec11fe35bcc0100000000ffffffff01328601000000000016\
-                 001493ce48570b55c42c2af816aeaba06cfee1224fae000000000001011fa086\
-                 01000000000016001493ce48570b55c42c2af816aeaba06cfee1224fae010304\
-                 010000000000",
-            )
-            .unwrap(),
-        )
-        .unwrap();
-
-        assert!(descriptor
-            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0), &Secp256k1::new())
-            .is_some());
-    }
-
-    #[test]
-    fn test_derive_from_psbt_input_pkh_tpub() {
-        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
-            "pkh([0f056943/44h/0h/0h]tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd/10/*)",
-        )
-        .unwrap();
-        let psbt = Psbt::deserialize(
-            &Vec::<u8>::from_hex(
-                "70736274ff010053010000000145843b86be54a3cd8c9e38444e1162676c00df\
-                 e7964122a70df491ea12fd67090100000000ffffffff01c19598000000000017\
-                 a91432bb94283282f72b2e034709e348c44d5a4db0ef8700000000000100f902\
-                 0000000001010167e99c0eb67640f3a1b6805f2d8be8238c947f8aaf49eb0a9c\
-                 bee6a42c984200000000171600142b29a22019cca05b9c2b2d283a4c4489e1cf\
-                 9f8ffeffffff02a01dced06100000017a914e2abf033cadbd74f0f4c74946201\
-                 decd20d5c43c8780969800000000001976a9148b0fce5fb1264e599a65387313\
-                 3c95478b902eb288ac02473044022015d9211576163fa5b001e84dfa3d44efd9\
-                 86b8f3a0d3d2174369288b2b750906022048dacc0e5d73ae42512fd2b97e2071\
-                 a8d0bce443b390b1fe0b8128fe70ec919e01210232dad1c5a67dcb0116d407e2\
-                 52584228ab7ec00e8b9779d0c3ffe8114fc1a7d2c80600000103040100000022\
-                 0603433b83583f8c4879b329dd08bbc7da935e4cc02f637ff746e05f0466ffb2\
-                 a6a2180f0569432c00008000000080000000800a000000000000000000",
-            )
-            .unwrap(),
-        )
-        .unwrap();
-
-        assert!(descriptor
-            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0), &Secp256k1::new())
-            .is_some());
-    }
-
-    #[test]
-    fn test_derive_from_psbt_input_wsh() {
-        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
-            "wsh(and_v(v:pk(03b6633fef2397a0a9de9d7b6f23aef8368a6e362b0581f0f0af70d5ecfd254b14),older(6)))",
-        )
-        .unwrap();
-        let psbt = Psbt::deserialize(
-            &Vec::<u8>::from_hex(
-                "70736274ff01005302000000011c8116eea34408ab6529223c9a176606742207\
-                 67a1ff1d46a6e3c4a88243ea6e01000000000600000001109698000000000017\
-                 a914ad105f61102e0d01d7af40d06d6a5c3ae2f7fde387000000000001012b80\
-                 969800000000002200203ca72f106a72234754890ca7640c43f65d2174e44d33\
-                 336030f9059345091044010304010000000105252103b6633fef2397a0a9de9d\
-                 7b6f23aef8368a6e362b0581f0f0af70d5ecfd254b14ad56b20000",
-            )
-            .unwrap(),
-        )
-        .unwrap();
-
-        assert!(descriptor
-            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0), &Secp256k1::new())
-            .is_some());
-    }
-
-    #[test]
-    fn test_derive_from_psbt_input_sh() {
-        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
-            "sh(and_v(v:pk(021403881a5587297818fcaf17d239cefca22fce84a45b3b1d23e836c4af671dbb),after(630000)))",
-        )
-        .unwrap();
-        let psbt = Psbt::deserialize(
-            &Vec::<u8>::from_hex(
-                "70736274ff0100530100000001bc8c13df445dfadcc42afa6dc841f85d22b01d\
-                 a6270ebf981740f4b7b1d800390000000000feffffff01ba9598000000000017\
-                 a91457b148ba4d3e5fa8608a8657875124e3d1c9390887f09c0900000100e002\
-                 0000000001016ba1bbe05cc93574a0d611ec7d93ad0ab6685b28d0cd80e8a82d\
-                 debb326643c90100000000feffffff02809698000000000017a914d9a6e8c455\
-                 8e16c8253afe53ce37ad61cf4c38c487403504cf6100000017a9144044fb6e0b\
-                 757dfc1b34886b6a95aef4d3db137e870247304402202a9b72d939bcde8ba2a1\
-                 e0980597e47af4f5c152a78499143c3d0a78ac2286a602207a45b1df9e93b8c9\
-                 6f09f5c025fe3e413ca4b905fe65ee55d32a3276439a9b8f012102dc1fcc2636\
-                 4da1aa718f03d8d9bd6f2ff410ed2cf1245a168aa3bcc995ac18e0a806000001\
-                 03040100000001042821021403881a5587297818fcaf17d239cefca22fce84a4\
-                 5b3b1d23e836c4af671dbbad03f09c09b10000",
-            )
-            .unwrap(),
-        )
-        .unwrap();
-
-        assert!(descriptor
-            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0), &Secp256k1::new())
-            .is_some());
-    }
-
-    #[test]
-    fn test_to_wallet_descriptor_fixup_networks() {
-        use crate::keys::{any_network, IntoDescriptorKey};
-
-        let secp = Secp256k1::new();
-
-        let xprv = bip32::Xpriv::from_str("xprv9s21ZrQH143K3c3gF1DUWpWNr2SG2XrG8oYPpqYh7hoWsJy9NjabErnzriJPpnGHyKz5NgdXmq1KVbqS1r4NXdCoKitWg5e86zqXHa8kxyB").unwrap();
-        let path = bip32::DerivationPath::from_str("m/0").unwrap();
-
-        // here `to_descriptor_key` will set the valid networks for the key to only mainnet, since
-        // we are using an "xpub"
-        let key = (xprv, path.clone()).into_descriptor_key().unwrap();
-        // override it with any. this happens in some key conversions, like bip39
-        let key = key.override_valid_networks(any_network());
-
-        // make a descriptor out of it
-        let desc = crate::descriptor!(wpkh(key)).unwrap();
-        // this should convert the key that supports "any_network" to the right network (testnet)
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-
-        let mut xprv_testnet = xprv;
-        xprv_testnet.network = Network::Testnet;
-
-        let xpub_testnet = bip32::Xpub::from_priv(&secp, &xprv_testnet);
-        let desc_pubkey = DescriptorPublicKey::XPub(DescriptorXKey {
-            xkey: xpub_testnet,
-            origin: None,
-            derivation_path: path,
-            wildcard: Wildcard::Unhardened,
-        });
-
-        assert_eq!(wallet_desc.to_string(), "wpkh(tpubD6NzVbkrYhZ4XtJzoDja5snUjBNQRP5B3f4Hyn1T1x6PVPxzzVjvw6nJx2D8RBCxog9GEVjZoyStfepTz7TtKoBVdkCtnc7VCJh9dD4RAU9/0/*)#a3svx0ha");
-        assert_eq!(
-            keymap
-                .get(&desc_pubkey)
-                .map(|key| key.to_public(&secp).unwrap()),
-            Some(desc_pubkey)
-        );
-    }
-
-    // test IntoWalletDescriptor trait from &str with and without checksum appended
-    #[test]
-    fn test_descriptor_from_str_with_checksum() {
-        let secp = Secp256k1::new();
-
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc62"
-            .into_wallet_descriptor(&secp, Network::Testnet);
-        assert!(desc.is_ok());
-
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
-            .into_wallet_descriptor(&secp, Network::Testnet);
-        assert!(desc.is_ok());
-
-        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)#67ju93jw"
-            .into_wallet_descriptor(&secp, Network::Testnet);
-        assert!(desc.is_ok());
-
-        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
-            .into_wallet_descriptor(&secp, Network::Testnet);
-        assert!(desc.is_ok());
-
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
-            .into_wallet_descriptor(&secp, Network::Testnet);
-        assert_matches!(desc, Err(DescriptorError::InvalidDescriptorChecksum));
-
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
-            .into_wallet_descriptor(&secp, Network::Testnet);
-        assert_matches!(desc, Err(DescriptorError::InvalidDescriptorChecksum));
-    }
-
-    // test IntoWalletDescriptor trait from &str with keys from right and wrong network
-    #[test]
-    fn test_descriptor_from_str_with_keys_network() {
-        let secp = Secp256k1::new();
-
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
-            .into_wallet_descriptor(&secp, Network::Testnet);
-        assert!(desc.is_ok());
-
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
-            .into_wallet_descriptor(&secp, Network::Regtest);
-        assert!(desc.is_ok());
-
-        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
-            .into_wallet_descriptor(&secp, Network::Testnet);
-        assert!(desc.is_ok());
-
-        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
-            .into_wallet_descriptor(&secp, Network::Regtest);
-        assert!(desc.is_ok());
-
-        let desc = "sh(wpkh(02864bb4ad00cefa806098a69e192bbda937494e69eb452b87bb3f20f6283baedb))"
-            .into_wallet_descriptor(&secp, Network::Testnet);
-        assert!(desc.is_ok());
-
-        let desc = "sh(wpkh(02864bb4ad00cefa806098a69e192bbda937494e69eb452b87bb3f20f6283baedb))"
-            .into_wallet_descriptor(&secp, Network::Bitcoin);
-        assert!(desc.is_ok());
-
-        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
-            .into_wallet_descriptor(&secp, Network::Bitcoin);
-        assert_matches!(desc, Err(DescriptorError::Key(KeyError::InvalidNetwork)));
-
-        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
-            .into_wallet_descriptor(&secp, Network::Bitcoin);
-        assert_matches!(desc, Err(DescriptorError::Key(KeyError::InvalidNetwork)));
-    }
-
-    // test IntoWalletDescriptor trait from the output of the descriptor!() macro
-    #[test]
-    fn test_descriptor_from_str_from_output_of_macro() {
-        let secp = Secp256k1::new();
-
-        let tpub = bip32::Xpub::from_str("tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK").unwrap();
-        let path = bip32::DerivationPath::from_str("m/1/2").unwrap();
-        let key = (tpub, path).into_descriptor_key().unwrap();
-
-        // make a descriptor out of it
-        let desc = crate::descriptor!(wpkh(key)).unwrap();
-
-        let (wallet_desc, _) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let wallet_desc_str = wallet_desc.to_string();
-        assert_eq!(wallet_desc_str, "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)#67ju93jw");
-
-        let (wallet_desc2, _) = wallet_desc_str
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        assert_eq!(wallet_desc, wallet_desc2)
-    }
-
-    #[test]
-    fn test_into_wallet_descriptor_checked() {
-        let secp = Secp256k1::new();
-
-        let descriptor = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0'/1/2/*)";
-        let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
-
-        assert_matches!(result, Err(DescriptorError::HardenedDerivationXpub));
-
-        let descriptor = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/<0;1>/*)";
-        let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
-
-        assert_matches!(result, Err(DescriptorError::MultiPath));
-
-        // repeated pubkeys
-        let descriptor = "wsh(multi(2,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*))";
-        let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
-
-        assert!(result.is_err());
-    }
-
-    #[test]
-    fn test_sh_wsh_sortedmulti_redeemscript() {
-        use miniscript::psbt::PsbtInputExt;
-
-        let secp = Secp256k1::new();
-
-        let descriptor = "sh(wsh(sortedmulti(3,tpubDEsqS36T4DVsKJd9UH8pAKzrkGBYPLEt9jZMwpKtzh1G6mgYehfHt9WCgk7MJG5QGSFWf176KaBNoXbcuFcuadAFKxDpUdMDKGBha7bY3QM/0/*,tpubDF3cpwfs7fMvXXuoQbohXtLjNM6ehwYT287LWtmLsd4r77YLg6MZg4vTETx5MSJ2zkfigbYWu31VA2Z2Vc1cZugCYXgS7FQu6pE8V6TriEH/0/*,tpubDE1SKfcW76Tb2AASv5bQWMuScYNAdoqLHoexw13sNDXwmUhQDBbCD3QAedKGLhxMrWQdMDKENzYtnXPDRvexQPNuDrLj52wAjHhNEm8sJ4p/0/*,tpubDFLc6oXwJmhm3FGGzXkfJNTh2KitoY3WhmmQvuAjMhD8YbyWn5mAqckbxXfm2etM3p5J6JoTpSrMqRSTfMLtNW46poDaEZJ1kjd3csRSjwH/0/*,tpubDEWD9NBeWP59xXmdqSNt4VYdtTGwbpyP8WS962BuqpQeMZmX9Pur14dhXdZT5a7wR1pK6dPtZ9fP5WR493hPzemnBvkfLLYxnUjAKj1JCQV/0/*,tpubDEHyZkkwd7gZWCTgQuYQ9C4myF2hMEmyHsBCCmLssGqoqUxeT3gzohF5uEVURkf9TtmeepJgkSUmteac38FwZqirjApzNX59XSHLcwaTZCH/0/*,tpubDEqLouCekwnMUWN486kxGzD44qVgeyuqHyxUypNEiQt5RnUZNJe386TKPK99fqRV1vRkZjYAjtXGTECz98MCsdLcnkM67U6KdYRzVubeCgZ/0/*)))";
-        let (descriptor, _) =
-            into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet).unwrap();
-
-        let descriptor = descriptor.at_derivation_index(0).unwrap();
-
-        let script = ScriptBuf::from_hex("5321022f533b667e2ea3b36e21961c9fe9dca340fbe0af5210173a83ae0337ab20a57621026bb53a98e810bd0ee61a0ed1164ba6c024786d76554e793e202dc6ce9c78c4ea2102d5b8a7d66a41ffdb6f4c53d61994022e886b4f45001fb158b95c9164d45f8ca3210324b75eead2c1f9c60e8adeb5e7009fec7a29afcdb30d829d82d09562fe8bae8521032d34f8932200833487bd294aa219dcbe000b9f9b3d824799541430009f0fa55121037468f8ea99b6c64788398b5ad25480cad08f4b0d65be54ce3a55fd206b5ae4722103f72d3d96663b0ea99b0aeb0d7f273cab11a8de37885f1dddc8d9112adb87169357ae").unwrap();
-
-        let mut psbt_input = psbt::Input::default();
-        psbt_input
-            .update_with_descriptor_unchecked(&descriptor)
-            .unwrap();
-
-        assert_eq!(psbt_input.redeem_script, Some(script.to_p2wsh()));
-        assert_eq!(psbt_input.witness_script, Some(script));
-    }
-}
-
-
\ No newline at end of file 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 deleted file mode 100644 index a88d919978..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/policy.rs.html +++ /dev/null @@ -1,3813 +0,0 @@ -policy.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
-1148
-1149
-1150
-1151
-1152
-1153
-1154
-1155
-1156
-1157
-1158
-1159
-1160
-1161
-1162
-1163
-1164
-1165
-1166
-1167
-1168
-1169
-1170
-1171
-1172
-1173
-1174
-1175
-1176
-1177
-1178
-1179
-1180
-1181
-1182
-1183
-1184
-1185
-1186
-1187
-1188
-1189
-1190
-1191
-1192
-1193
-1194
-1195
-1196
-1197
-1198
-1199
-1200
-1201
-1202
-1203
-1204
-1205
-1206
-1207
-1208
-1209
-1210
-1211
-1212
-1213
-1214
-1215
-1216
-1217
-1218
-1219
-1220
-1221
-1222
-1223
-1224
-1225
-1226
-1227
-1228
-1229
-1230
-1231
-1232
-1233
-1234
-1235
-1236
-1237
-1238
-1239
-1240
-1241
-1242
-1243
-1244
-1245
-1246
-1247
-1248
-1249
-1250
-1251
-1252
-1253
-1254
-1255
-1256
-1257
-1258
-1259
-1260
-1261
-1262
-1263
-1264
-1265
-1266
-1267
-1268
-1269
-1270
-1271
-1272
-1273
-1274
-1275
-1276
-1277
-1278
-1279
-1280
-1281
-1282
-1283
-1284
-1285
-1286
-1287
-1288
-1289
-1290
-1291
-1292
-1293
-1294
-1295
-1296
-1297
-1298
-1299
-1300
-1301
-1302
-1303
-1304
-1305
-1306
-1307
-1308
-1309
-1310
-1311
-1312
-1313
-1314
-1315
-1316
-1317
-1318
-1319
-1320
-1321
-1322
-1323
-1324
-1325
-1326
-1327
-1328
-1329
-1330
-1331
-1332
-1333
-1334
-1335
-1336
-1337
-1338
-1339
-1340
-1341
-1342
-1343
-1344
-1345
-1346
-1347
-1348
-1349
-1350
-1351
-1352
-1353
-1354
-1355
-1356
-1357
-1358
-1359
-1360
-1361
-1362
-1363
-1364
-1365
-1366
-1367
-1368
-1369
-1370
-1371
-1372
-1373
-1374
-1375
-1376
-1377
-1378
-1379
-1380
-1381
-1382
-1383
-1384
-1385
-1386
-1387
-1388
-1389
-1390
-1391
-1392
-1393
-1394
-1395
-1396
-1397
-1398
-1399
-1400
-1401
-1402
-1403
-1404
-1405
-1406
-1407
-1408
-1409
-1410
-1411
-1412
-1413
-1414
-1415
-1416
-1417
-1418
-1419
-1420
-1421
-1422
-1423
-1424
-1425
-1426
-1427
-1428
-1429
-1430
-1431
-1432
-1433
-1434
-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
-1596
-1597
-1598
-1599
-1600
-1601
-1602
-1603
-1604
-1605
-1606
-1607
-1608
-1609
-1610
-1611
-1612
-1613
-1614
-1615
-1616
-1617
-1618
-1619
-1620
-1621
-1622
-1623
-1624
-1625
-1626
-1627
-1628
-1629
-1630
-1631
-1632
-1633
-1634
-1635
-1636
-1637
-1638
-1639
-1640
-1641
-1642
-1643
-1644
-1645
-1646
-1647
-1648
-1649
-1650
-1651
-1652
-1653
-1654
-1655
-1656
-1657
-1658
-1659
-1660
-1661
-1662
-1663
-1664
-1665
-1666
-1667
-1668
-1669
-1670
-1671
-1672
-1673
-1674
-1675
-1676
-1677
-1678
-1679
-1680
-1681
-1682
-1683
-1684
-1685
-1686
-1687
-1688
-1689
-1690
-1691
-1692
-1693
-1694
-1695
-1696
-1697
-1698
-1699
-1700
-1701
-1702
-1703
-1704
-1705
-1706
-1707
-1708
-1709
-1710
-1711
-1712
-1713
-1714
-1715
-1716
-1717
-1718
-1719
-1720
-1721
-1722
-1723
-1724
-1725
-1726
-1727
-1728
-1729
-1730
-1731
-1732
-1733
-1734
-1735
-1736
-1737
-1738
-1739
-1740
-1741
-1742
-1743
-1744
-1745
-1746
-1747
-1748
-1749
-1750
-1751
-1752
-1753
-1754
-1755
-1756
-1757
-1758
-1759
-1760
-1761
-1762
-1763
-1764
-1765
-1766
-1767
-1768
-1769
-1770
-1771
-1772
-1773
-1774
-1775
-1776
-1777
-1778
-1779
-1780
-1781
-1782
-1783
-1784
-1785
-1786
-1787
-1788
-1789
-1790
-1791
-1792
-1793
-1794
-1795
-1796
-1797
-1798
-1799
-1800
-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
-
// 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.
-
-//! 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.
-//!
-//! ## Example
-//!
-//! ```
-//! # use std::sync::Arc;
-//! # use bdk::descriptor::*;
-//! # use bdk::wallet::signer::*;
-//! # use bdk::bitcoin::secp256k1::Secp256k1;
-//! use bdk::descriptor::policy::BuildSatisfaction;
-//! let secp = Secp256k1::new();
-//! let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
-//!
-//! let (extended_desc, key_map) = ExtendedDescriptor::parse_descriptor(&secp, desc)?;
-//! println!("{:?}", extended_desc);
-//!
-//! 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).unwrap());
-//! # Ok::<(), anyhow::Error>(())
-//! ```
-
-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};
-
-use bitcoin::bip32::Fingerprint;
-use bitcoin::hashes::{hash160, ripemd160, sha256};
-use bitcoin::{absolute, key::XOnlyPublicKey, PublicKey, Sequence};
-
-use miniscript::descriptor::{
-    DescriptorPublicKey, ShInner, SinglePub, SinglePubKey, SortedMultiVec, WshInner,
-};
-use miniscript::hash256;
-use miniscript::{
-    Descriptor, Miniscript, Satisfier, ScriptContext, SigType, Terminal, ToPublicKey,
-};
-
-use crate::descriptor::ExtractPolicy;
-use crate::keys::ExtScriptContext;
-use crate::wallet::signer::{SignerId, SignersContainer};
-use crate::wallet::utils::{After, Older, SecpCtx};
-
-use super::checksum::calc_checksum;
-use super::error::Error;
-use super::XKeyUtils;
-use bitcoin::psbt::{self, Psbt};
-use miniscript::psbt::PsbtInputSatisfier;
-
-/// A unique identifier for a key
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
-#[serde(rename_all = "snake_case")]
-pub enum PkOrF {
-    /// A legacy public key
-    Pubkey(PublicKey),
-    /// A x-only public key
-    XOnlyPubkey(XOnlyPublicKey),
-    /// An extended key fingerprint
-    Fingerprint(Fingerprint),
-}
-
-impl PkOrF {
-    fn from_key(k: &DescriptorPublicKey, secp: &SecpCtx) -> Self {
-        match k {
-            DescriptorPublicKey::Single(SinglePub {
-                key: SinglePubKey::FullKey(pk),
-                ..
-            }) => PkOrF::Pubkey(*pk),
-            DescriptorPublicKey::Single(SinglePub {
-                key: SinglePubKey::XOnly(pk),
-                ..
-            }) => PkOrF::XOnlyPubkey(*pk),
-            DescriptorPublicKey::XPub(xpub) => PkOrF::Fingerprint(xpub.root_fingerprint(secp)),
-            DescriptorPublicKey::MultiXPub(multi) => {
-                PkOrF::Fingerprint(multi.root_fingerprint(secp))
-            }
-        }
-    }
-}
-
-/// An item that needs to be satisfied
-#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
-#[serde(tag = "type", rename_all = "UPPERCASE")]
-pub enum SatisfiableItem {
-    // Leaves
-    /// ECDSA Signature for a raw public key
-    EcdsaSignature(PkOrF),
-    /// Schnorr Signature for a raw public key
-    SchnorrSignature(PkOrF),
-    /// SHA256 preimage hash
-    Sha256Preimage {
-        /// The digest value
-        hash: sha256::Hash,
-    },
-    /// Double SHA256 preimage hash
-    Hash256Preimage {
-        /// The digest value
-        hash: hash256::Hash,
-    },
-    /// RIPEMD160 preimage hash
-    Ripemd160Preimage {
-        /// The digest value
-        hash: ripemd160::Hash,
-    },
-    /// SHA256 then RIPEMD160 preimage hash
-    Hash160Preimage {
-        /// The digest value
-        hash: hash160::Hash,
-    },
-    /// Absolute timeclock timestamp
-    AbsoluteTimelock {
-        /// The timelock value
-        value: absolute::LockTime,
-    },
-    /// Relative timelock locktime
-    RelativeTimelock {
-        /// The timelock value
-        value: Sequence,
-    },
-    /// Multi-signature public keys with threshold count
-    Multisig {
-        /// The raw public key or extended key fingerprint
-        keys: Vec<PkOrF>,
-        /// The required threshold count
-        threshold: usize,
-    },
-
-    // Complex item
-    /// Threshold items with threshold count
-    Thresh {
-        /// The policy items
-        items: Vec<Policy>,
-        /// The required threshold count
-        threshold: usize,
-    },
-}
-
-impl SatisfiableItem {
-    /// Returns whether the [`SatisfiableItem`] is a leaf item
-    pub fn is_leaf(&self) -> bool {
-        !matches!(
-            self,
-            SatisfiableItem::Thresh {
-                items: _,
-                threshold: _,
-            }
-        )
-    }
-
-    /// Returns a unique id for the [`SatisfiableItem`]
-    pub fn id(&self) -> String {
-        calc_checksum(&serde_json::to_string(self).expect("Failed to serialize a SatisfiableItem"))
-            .expect("Failed to compute a SatisfiableItem id")
-    }
-}
-
-fn combinations(vec: &[usize], size: usize) -> Vec<Vec<usize>> {
-    assert!(vec.len() >= size);
-
-    let mut answer = Vec::new();
-
-    let mut queue = VecDeque::new();
-    for (index, val) in vec.iter().enumerate() {
-        let mut new_vec = Vec::with_capacity(size);
-        new_vec.push(*val);
-        queue.push_back((index, new_vec));
-    }
-
-    while let Some((index, vals)) = queue.pop_front() {
-        if vals.len() >= size {
-            answer.push(vals);
-        } else {
-            for (new_index, val) in vec.iter().skip(index + 1).enumerate() {
-                let mut cloned = vals.clone();
-                cloned.push(*val);
-                queue.push_front((new_index, cloned));
-            }
-        }
-    }
-
-    answer
-}
-
-fn mix<T: Clone>(vec: Vec<Vec<T>>) -> Vec<Vec<T>> {
-    if vec.is_empty() || vec.iter().any(Vec::is_empty) {
-        return vec![];
-    }
-
-    let mut answer = Vec::new();
-    let size = vec.len();
-
-    let mut queue = VecDeque::new();
-    for i in &vec[0] {
-        let mut new_vec = Vec::with_capacity(size);
-        new_vec.push(i.clone());
-        queue.push_back(new_vec);
-    }
-
-    while let Some(vals) = queue.pop_front() {
-        if vals.len() >= size {
-            answer.push(vals);
-        } else {
-            let level = vals.len();
-            for i in &vec[level] {
-                let mut cloned = vals.clone();
-                cloned.push(i.clone());
-                queue.push_front(cloned);
-            }
-        }
-    }
-
-    answer
-}
-
-/// Type for a map of sets of [`Condition`] items keyed by each set's index
-pub type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
-/// Type for a map of folded sets of [`Condition`] items keyed by a vector of the combined set's indexes
-pub type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
-
-fn serialize_folded_cond_map<S>(
-    input_map: &FoldedConditionMap,
-    serializer: S,
-) -> Result<S::Ok, S::Error>
-where
-    S: Serializer,
-{
-    let mut map = serializer.serialize_map(Some(input_map.len()))?;
-    for (k, v) in input_map {
-        let k_string = format!("{:?}", k);
-        map.serialize_entry(&k_string, v)?;
-    }
-    map.end()
-}
-
-/// Represent if and how much a policy item is satisfied by the wallet's descriptor
-#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
-#[serde(tag = "type", rename_all = "UPPERCASE")]
-pub enum Satisfaction {
-    /// Only a partial satisfaction of some kind of threshold policy
-    Partial {
-        /// Total number of items
-        n: usize,
-        /// Threshold
-        m: usize,
-        /// The items that can be satisfied by the descriptor or are satisfied in the PSBT
-        items: Vec<usize>,
-        #[serde(skip_serializing_if = "Option::is_none")]
-        /// Whether the items are sorted in lexicographic order (used by `sortedmulti`)
-        sorted: Option<bool>,
-        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
-        /// Extra conditions that also need to be satisfied
-        conditions: ConditionMap,
-    },
-    /// Can reach the threshold of some kind of threshold policy
-    PartialComplete {
-        /// Total number of items
-        n: usize,
-        /// Threshold
-        m: usize,
-        /// The items that can be satisfied by the descriptor
-        items: Vec<usize>,
-        #[serde(skip_serializing_if = "Option::is_none")]
-        /// Whether the items are sorted in lexicographic order (used by `sortedmulti`)
-        sorted: Option<bool>,
-        #[serde(
-            serialize_with = "serialize_folded_cond_map",
-            skip_serializing_if = "BTreeMap::is_empty"
-        )]
-        /// Extra conditions that also need to be satisfied
-        conditions: FoldedConditionMap,
-    },
-
-    /// Can satisfy the policy item
-    Complete {
-        /// Extra conditions that also need to be satisfied
-        condition: Condition,
-    },
-    /// Cannot satisfy or contribute to the policy item
-    None,
-}
-
-impl Satisfaction {
-    /// Returns whether the [`Satisfaction`] is a leaf item
-    pub fn is_leaf(&self) -> bool {
-        match self {
-            Satisfaction::None | Satisfaction::Complete { .. } => true,
-            Satisfaction::PartialComplete { .. } | Satisfaction::Partial { .. } => false,
-        }
-    }
-
-    // add `inner` as one of self's partial items. this only makes sense on partials
-    fn add(&mut self, inner: &Satisfaction, inner_index: usize) -> Result<(), PolicyError> {
-        match self {
-            Satisfaction::None | Satisfaction::Complete { .. } => Err(PolicyError::AddOnLeaf),
-            Satisfaction::PartialComplete { .. } => Err(PolicyError::AddOnPartialComplete),
-            Satisfaction::Partial {
-                n,
-                ref mut conditions,
-                ref mut items,
-                ..
-            } => {
-                if inner_index >= *n || items.contains(&inner_index) {
-                    return Err(PolicyError::IndexOutOfRange(inner_index));
-                }
-
-                match inner {
-                    // not relevant if not completed yet
-                    Satisfaction::None | Satisfaction::Partial { .. } => return Ok(()),
-                    Satisfaction::Complete { condition } => {
-                        items.push(inner_index);
-                        conditions.insert(inner_index, vec![*condition].into_iter().collect());
-                    }
-                    Satisfaction::PartialComplete {
-                        conditions: other_conditions,
-                        ..
-                    } => {
-                        items.push(inner_index);
-                        let conditions_set = other_conditions
-                            .values()
-                            .fold(HashSet::new(), |set, i| set.union(i).cloned().collect());
-                        conditions.insert(inner_index, conditions_set);
-                    }
-                }
-
-                Ok(())
-            }
-        }
-    }
-
-    fn finalize(&mut self) {
-        // if partial try to bump it to a partialcomplete
-        if let Satisfaction::Partial {
-            n,
-            m,
-            items,
-            conditions,
-            sorted,
-        } = self
-        {
-            if items.len() >= *m {
-                let mut map = BTreeMap::new();
-                let indexes = combinations(items, *m);
-                // `indexes` at this point is a Vec<Vec<usize>>, with the "n choose k" of items (m of n)
-                indexes
-                    .into_iter()
-                    // .inspect(|x| println!("--- orig --- {:?}", x))
-                    // we map each of the combinations of elements into a tuple of ([chosen items], [conditions]). unfortunately, those items have potentially more than one
-                    // condition (think about ORs), so we also use `mix` to expand those, i.e. [[0], [1, 2]] becomes [[0, 1], [0, 2]]. This is necessary to make sure that we
-                    // consider every possible options and check whether or not they are compatible.
-                    // since this step can turn one item of the iterator into multiple ones, we use `flat_map()` to expand them out
-                    .flat_map(|i_vec| {
-                        mix(i_vec
-                            .iter()
-                            .map(|i| {
-                                conditions
-                                    .get(i)
-                                    .map(|set| set.clone().into_iter().collect())
-                                    .unwrap_or_default()
-                            })
-                            .collect())
-                        .into_iter()
-                        .map(|x| (i_vec.clone(), x))
-                        .collect::<Vec<(Vec<usize>, Vec<Condition>)>>()
-                    })
-                    // .inspect(|x| println!("flat {:?}", x))
-                    // try to fold all the conditions for this specific combination of indexes/options. if they are not compatible, try_fold will be Err
-                    .map(|(key, val)| {
-                        (
-                            key,
-                            val.into_iter()
-                                .try_fold(Condition::default(), |acc, v| acc.merge(&v)),
-                        )
-                    })
-                    // .inspect(|x| println!("try_fold {:?}", x))
-                    // filter out all the incompatible combinations
-                    .filter(|(_, val)| val.is_ok())
-                    // .inspect(|x| println!("filter {:?}", x))
-                    // push them into the map
-                    .for_each(|(key, val)| {
-                        map.entry(key)
-                            .or_insert_with(HashSet::new)
-                            .insert(val.unwrap());
-                    });
-                // TODO: if the map is empty, the conditions are not compatible, return an error?
-                *self = Satisfaction::PartialComplete {
-                    n: *n,
-                    m: *m,
-                    items: items.clone(),
-                    conditions: map,
-                    sorted: *sorted,
-                };
-            }
-        }
-    }
-}
-
-impl From<bool> for Satisfaction {
-    fn from(other: bool) -> Self {
-        if other {
-            Satisfaction::Complete {
-                condition: Default::default(),
-            }
-        } else {
-            Satisfaction::None
-        }
-    }
-}
-
-/// Descriptor spending policy
-#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
-pub struct Policy {
-    /// Identifier for this policy node
-    pub id: String,
-
-    /// Type of this policy node
-    #[serde(flatten)]
-    pub item: SatisfiableItem,
-    /// How much a given PSBT already satisfies this policy node in terms of signatures
-    pub satisfaction: Satisfaction,
-    /// How the wallet's descriptor can satisfy this policy node
-    pub contribution: Satisfaction,
-}
-
-/// An extra condition that must be satisfied but that is out of control of the user
-/// TODO: use `bitcoin::LockTime` and `bitcoin::Sequence`
-#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Default, Serialize)]
-pub struct Condition {
-    /// Optional CheckSequenceVerify condition
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub csv: Option<Sequence>,
-    /// Optional timelock condition
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub timelock: Option<absolute::LockTime>,
-}
-
-impl Condition {
-    fn merge_nlocktime(
-        a: absolute::LockTime,
-        b: absolute::LockTime,
-    ) -> Result<absolute::LockTime, PolicyError> {
-        if !a.is_same_unit(b) {
-            Err(PolicyError::MixedTimelockUnits)
-        } else if a > b {
-            Ok(a)
-        } else {
-            Ok(b)
-        }
-    }
-
-    fn merge_nsequence(a: Sequence, b: Sequence) -> Result<Sequence, PolicyError> {
-        if a.is_time_locked() != b.is_time_locked() {
-            Err(PolicyError::MixedTimelockUnits)
-        } else {
-            Ok(max(a, b))
-        }
-    }
-
-    pub(crate) fn merge(mut self, other: &Condition) -> Result<Self, PolicyError> {
-        match (self.csv, other.csv) {
-            (Some(a), Some(b)) => self.csv = Some(Self::merge_nsequence(a, b)?),
-            (None, any) => self.csv = any,
-            _ => {}
-        }
-
-        match (self.timelock, other.timelock) {
-            (Some(a), Some(b)) => self.timelock = Some(Self::merge_nlocktime(a, b)?),
-            (None, any) => self.timelock = any,
-            _ => {}
-        }
-
-        Ok(self)
-    }
-
-    /// Returns `true` if there are no extra conditions to verify
-    pub fn is_null(&self) -> bool {
-        self.csv.is_none() && self.timelock.is_none()
-    }
-}
-
-/// Errors that can happen while extracting and manipulating policies
-#[derive(Debug, PartialEq, Eq)]
-pub enum PolicyError {
-    /// Not enough items are selected to satisfy a [`SatisfiableItem::Thresh`] or a [`SatisfiableItem::Multisig`]
-    NotEnoughItemsSelected(String),
-    /// Index out of range for an item to satisfy a [`SatisfiableItem::Thresh`] or a [`SatisfiableItem::Multisig`]
-    IndexOutOfRange(usize),
-    /// Can not add to an item that is [`Satisfaction::None`] or [`Satisfaction::Complete`]
-    AddOnLeaf,
-    /// Can not add to an item that is [`Satisfaction::PartialComplete`]
-    AddOnPartialComplete,
-    /// Can not merge CSV or timelock values unless both are less than or both are equal or greater than 500_000_000
-    MixedTimelockUnits,
-    /// Incompatible conditions (not currently used)
-    IncompatibleConditions,
-}
-
-impl fmt::Display for PolicyError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::NotEnoughItemsSelected(err) => write!(f, "Not enough items selected: {}", err),
-            Self::IndexOutOfRange(index) => write!(f, "Index out of range: {}", index),
-            Self::AddOnLeaf => write!(f, "Add on leaf"),
-            Self::AddOnPartialComplete => write!(f, "Add on partial complete"),
-            Self::MixedTimelockUnits => write!(f, "Mixed timelock units"),
-            Self::IncompatibleConditions => write!(f, "Incompatible conditions"),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for PolicyError {}
-
-impl Policy {
-    fn new(item: SatisfiableItem) -> Self {
-        Policy {
-            id: item.id(),
-            item,
-            satisfaction: Satisfaction::None,
-            contribution: Satisfaction::None,
-        }
-    }
-
-    fn make_and(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
-        match (a, b) {
-            (None, None) => Ok(None),
-            (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
-            (Some(a), Some(b)) => Self::make_thresh(vec![a, b], 2),
-        }
-    }
-
-    fn make_or(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
-        match (a, b) {
-            (None, None) => Ok(None),
-            (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
-            (Some(a), Some(b)) => Self::make_thresh(vec![a, b], 1),
-        }
-    }
-
-    fn make_thresh(items: Vec<Policy>, threshold: usize) -> Result<Option<Policy>, PolicyError> {
-        if threshold == 0 {
-            return Ok(None);
-        }
-
-        let mut contribution = Satisfaction::Partial {
-            n: items.len(),
-            m: threshold,
-            items: vec![],
-            conditions: Default::default(),
-            sorted: None,
-        };
-        let mut satisfaction = contribution.clone();
-        for (index, item) in items.iter().enumerate() {
-            contribution.add(&item.contribution, index)?;
-            satisfaction.add(&item.satisfaction, index)?;
-        }
-
-        contribution.finalize();
-        satisfaction.finalize();
-
-        let mut policy: Policy = SatisfiableItem::Thresh { items, threshold }.into();
-        policy.contribution = contribution;
-        policy.satisfaction = satisfaction;
-
-        Ok(Some(policy))
-    }
-
-    fn make_multisig<Ctx: ScriptContext + 'static>(
-        keys: &[DescriptorPublicKey],
-        signers: &SignersContainer,
-        build_sat: BuildSatisfaction,
-        threshold: usize,
-        sorted: bool,
-        secp: &SecpCtx,
-    ) -> Result<Option<Policy>, PolicyError> {
-        if threshold == 0 {
-            return Ok(None);
-        }
-
-        let parsed_keys = keys.iter().map(|k| PkOrF::from_key(k, secp)).collect();
-
-        let mut contribution = Satisfaction::Partial {
-            n: keys.len(),
-            m: threshold,
-            items: vec![],
-            conditions: Default::default(),
-            sorted: Some(sorted),
-        };
-        let mut satisfaction = contribution.clone();
-
-        for (index, key) in keys.iter().enumerate() {
-            if signers.find(signer_id(key, secp)).is_some() {
-                contribution.add(
-                    &Satisfaction::Complete {
-                        condition: Default::default(),
-                    },
-                    index,
-                )?;
-            }
-
-            if let Some(psbt) = build_sat.psbt() {
-                if Ctx::find_signature(psbt, key, secp) {
-                    satisfaction.add(
-                        &Satisfaction::Complete {
-                            condition: Default::default(),
-                        },
-                        index,
-                    )?;
-                }
-            }
-        }
-        satisfaction.finalize();
-        contribution.finalize();
-
-        let mut policy: Policy = SatisfiableItem::Multisig {
-            keys: parsed_keys,
-            threshold,
-        }
-        .into();
-        policy.contribution = contribution;
-        policy.satisfaction = satisfaction;
-
-        Ok(Some(policy))
-    }
-
-    /// 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.
-    pub fn requires_path(&self) -> bool {
-        self.get_condition(&BTreeMap::new()).is_err()
-    }
-
-    /// Return the conditions that are set by the spending policy for a given path in the
-    /// policy tree
-    pub fn get_condition(
-        &self,
-        path: &BTreeMap<String, Vec<usize>>,
-    ) -> Result<Condition, PolicyError> {
-        // if items.len() == threshold, selected can be omitted and we take all of them by default
-        let default = match &self.item {
-            SatisfiableItem::Thresh { items, threshold } if items.len() == *threshold => {
-                (0..*threshold).collect()
-            }
-            SatisfiableItem::Multisig { keys, .. } => (0..keys.len()).collect(),
-            _ => HashSet::new(),
-        };
-        let selected: HashSet<_> = match path.get(&self.id) {
-            Some(arr) => arr.iter().copied().collect(),
-            _ => default,
-        };
-
-        match &self.item {
-            SatisfiableItem::Thresh { items, threshold } => {
-                let mapped_req = items
-                    .iter()
-                    .map(|i| i.get_condition(path))
-                    .collect::<Vec<_>>();
-
-                // if all the requirements are null we don't care about `selected` because there
-                // are no requirements
-                if mapped_req
-                    .iter()
-                    .all(|cond| matches!(cond, Ok(c) if c.is_null()))
-                {
-                    return Ok(Condition::default());
-                }
-
-                // make sure all the indexes in the `selected` list are within range
-                for index in &selected {
-                    if *index >= items.len() {
-                        return Err(PolicyError::IndexOutOfRange(*index));
-                    }
-                }
-
-                // if we have something, make sure we have enough items. note that the user can set
-                // an empty value for this step in case of n-of-n, because `selected` is set to all
-                // the elements above
-                if selected.len() < *threshold {
-                    return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()));
-                }
-
-                // check the selected items, see if there are conflicting requirements
-                mapped_req
-                    .into_iter()
-                    .enumerate()
-                    .filter(|(index, _)| selected.contains(index))
-                    .try_fold(Condition::default(), |acc, (_, cond)| acc.merge(&cond?))
-            }
-            SatisfiableItem::Multisig { keys, threshold } => {
-                if selected.len() < *threshold {
-                    return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()));
-                }
-                if let Some(item) = selected.into_iter().find(|&i| i >= keys.len()) {
-                    return Err(PolicyError::IndexOutOfRange(item));
-                }
-
-                Ok(Condition::default())
-            }
-            SatisfiableItem::AbsoluteTimelock { value } => Ok(Condition {
-                csv: None,
-                timelock: Some(*value),
-            }),
-            SatisfiableItem::RelativeTimelock { value } => Ok(Condition {
-                csv: Some(*value),
-                timelock: None,
-            }),
-            _ => Ok(Condition::default()),
-        }
-    }
-}
-
-impl From<SatisfiableItem> for Policy {
-    fn from(other: SatisfiableItem) -> Self {
-        Self::new(other)
-    }
-}
-
-fn signer_id(key: &DescriptorPublicKey, secp: &SecpCtx) -> SignerId {
-    // For consistency we always compute the key hash in "ecdsa" form (with the leading sign
-    // prefix) even if we are in a taproot descriptor. We just want some kind of unique identifier
-    // for a key, so it doesn't really matter how the identifier is computed.
-    match key {
-        DescriptorPublicKey::Single(SinglePub {
-            key: SinglePubKey::FullKey(pk),
-            ..
-        }) => pk.to_pubkeyhash(SigType::Ecdsa).into(),
-        DescriptorPublicKey::Single(SinglePub {
-            key: SinglePubKey::XOnly(pk),
-            ..
-        }) => pk.to_pubkeyhash(SigType::Ecdsa).into(),
-        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint(secp).into(),
-        DescriptorPublicKey::MultiXPub(xpub) => xpub.root_fingerprint(secp).into(),
-    }
-}
-
-fn make_generic_signature<M: Fn() -> SatisfiableItem, F: Fn(&Psbt) -> bool>(
-    key: &DescriptorPublicKey,
-    signers: &SignersContainer,
-    build_sat: BuildSatisfaction,
-    secp: &SecpCtx,
-    make_policy: M,
-    find_sig: F,
-) -> Policy {
-    let mut policy: Policy = make_policy().into();
-
-    policy.contribution = if signers.find(signer_id(key, secp)).is_some() {
-        Satisfaction::Complete {
-            condition: Default::default(),
-        }
-    } else {
-        Satisfaction::None
-    };
-
-    if let Some(psbt) = build_sat.psbt() {
-        policy.satisfaction = if find_sig(psbt) {
-            Satisfaction::Complete {
-                condition: Default::default(),
-            }
-        } else {
-            Satisfaction::None
-        };
-    }
-
-    policy
-}
-
-fn generic_sig_in_psbt<
-    // C is for "check", it's a closure we use to *check* if a psbt input contains the signature
-    // for a specific key
-    C: Fn(&psbt::Input, &SinglePubKey) -> bool,
-    // E is for "extract", it extracts a key from the bip32 derivations found in the psbt input
-    E: Fn(&psbt::Input, Fingerprint) -> Option<SinglePubKey>,
->(
-    psbt: &Psbt,
-    key: &DescriptorPublicKey,
-    secp: &SecpCtx,
-    check: C,
-    extract: E,
-) -> bool {
-    //TODO check signature validity
-    psbt.inputs.iter().all(|input| match key {
-        DescriptorPublicKey::Single(SinglePub { key, .. }) => check(input, key),
-        DescriptorPublicKey::XPub(xpub) => {
-            //TODO check actual derivation matches
-            match extract(input, xpub.root_fingerprint(secp)) {
-                Some(pubkey) => check(input, &pubkey),
-                None => false,
-            }
-        }
-        DescriptorPublicKey::MultiXPub(xpub) => {
-            //TODO check actual derivation matches
-            match extract(input, xpub.root_fingerprint(secp)) {
-                Some(pubkey) => check(input, &pubkey),
-                None => false,
-            }
-        }
-    })
-}
-
-trait SigExt: ScriptContext {
-    fn make_signature(
-        key: &DescriptorPublicKey,
-        signers: &SignersContainer,
-        build_sat: BuildSatisfaction,
-        secp: &SecpCtx,
-    ) -> Policy;
-
-    fn find_signature(psbt: &Psbt, key: &DescriptorPublicKey, secp: &SecpCtx) -> bool;
-}
-
-impl<T: ScriptContext + 'static> SigExt for T {
-    fn make_signature(
-        key: &DescriptorPublicKey,
-        signers: &SignersContainer,
-        build_sat: BuildSatisfaction,
-        secp: &SecpCtx,
-    ) -> Policy {
-        if T::as_enum().is_taproot() {
-            make_generic_signature(
-                key,
-                signers,
-                build_sat,
-                secp,
-                || SatisfiableItem::SchnorrSignature(PkOrF::from_key(key, secp)),
-                |psbt| Self::find_signature(psbt, key, secp),
-            )
-        } else {
-            make_generic_signature(
-                key,
-                signers,
-                build_sat,
-                secp,
-                || SatisfiableItem::EcdsaSignature(PkOrF::from_key(key, secp)),
-                |psbt| Self::find_signature(psbt, key, secp),
-            )
-        }
-    }
-
-    fn find_signature(psbt: &Psbt, key: &DescriptorPublicKey, secp: &SecpCtx) -> bool {
-        if T::as_enum().is_taproot() {
-            generic_sig_in_psbt(
-                psbt,
-                key,
-                secp,
-                |input, pk| {
-                    let pk = match pk {
-                        SinglePubKey::XOnly(pk) => pk,
-                        _ => return false,
-                    };
-
-                    if input.tap_internal_key == Some(*pk) && input.tap_key_sig.is_some() {
-                        true
-                    } else {
-                        input.tap_script_sigs.keys().any(|(sk, _)| sk == pk)
-                    }
-                },
-                |input, fing| {
-                    input
-                        .tap_key_origins
-                        .iter()
-                        .find(|(_, (_, (f, _)))| f == &fing)
-                        .map(|(pk, _)| SinglePubKey::XOnly(*pk))
-                },
-            )
-        } else {
-            generic_sig_in_psbt(
-                psbt,
-                key,
-                secp,
-                |input, pk| match pk {
-                    SinglePubKey::FullKey(pk) => input.partial_sigs.contains_key(pk),
-                    _ => false,
-                },
-                |input, fing| {
-                    input
-                        .bip32_derivation
-                        .iter()
-                        .find(|(_, (f, _))| f == &fing)
-                        .map(|(pk, _)| SinglePubKey::FullKey(PublicKey::new(*pk)))
-                },
-            )
-        }
-    }
-}
-
-impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
-    fn extract_policy(
-        &self,
-        signers: &SignersContainer,
-        build_sat: BuildSatisfaction,
-        secp: &SecpCtx,
-    ) -> Result<Option<Policy>, Error> {
-        Ok(match &self.node {
-            // Leaves
-            Terminal::True | Terminal::False => None,
-            Terminal::PkK(pubkey) => Some(Ctx::make_signature(pubkey, signers, build_sat, secp)),
-            Terminal::PkH(pubkey_hash) => {
-                Some(Ctx::make_signature(pubkey_hash, signers, build_sat, secp))
-            }
-            Terminal::After(value) => {
-                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock {
-                    value: (*value).into(),
-                }
-                .into();
-                policy.contribution = Satisfaction::Complete {
-                    condition: Condition {
-                        timelock: Some((*value).into()),
-                        csv: None,
-                    },
-                };
-                if let BuildSatisfaction::PsbtTimelocks {
-                    current_height,
-                    psbt,
-                    ..
-                } = build_sat
-                {
-                    let after = After::new(Some(current_height), false);
-                    let after_sat =
-                        Satisfier::<bitcoin::PublicKey>::check_after(&after, (*value).into());
-                    let inputs_sat = psbt_inputs_sat(psbt).all(|sat| {
-                        Satisfier::<bitcoin::PublicKey>::check_after(&sat, (*value).into())
-                    });
-                    if after_sat && inputs_sat {
-                        policy.satisfaction = policy.contribution.clone();
-                    }
-                }
-
-                Some(policy)
-            }
-            Terminal::Older(value) => {
-                let mut policy: Policy = SatisfiableItem::RelativeTimelock { value: *value }.into();
-                policy.contribution = Satisfaction::Complete {
-                    condition: Condition {
-                        timelock: None,
-                        csv: Some(*value),
-                    },
-                };
-                if let BuildSatisfaction::PsbtTimelocks {
-                    current_height,
-                    input_max_height,
-                    psbt,
-                } = build_sat
-                {
-                    let older = Older::new(Some(current_height), Some(input_max_height), false);
-                    let older_sat = Satisfier::<bitcoin::PublicKey>::check_older(&older, *value);
-                    let inputs_sat = psbt_inputs_sat(psbt)
-                        .all(|sat| Satisfier::<bitcoin::PublicKey>::check_older(&sat, *value));
-                    if older_sat && inputs_sat {
-                        policy.satisfaction = policy.contribution.clone();
-                    }
-                }
-
-                Some(policy)
-            }
-            Terminal::Sha256(hash) => Some(SatisfiableItem::Sha256Preimage { hash: *hash }.into()),
-            Terminal::Hash256(hash) => {
-                Some(SatisfiableItem::Hash256Preimage { hash: *hash }.into())
-            }
-            Terminal::Ripemd160(hash) => {
-                Some(SatisfiableItem::Ripemd160Preimage { hash: *hash }.into())
-            }
-            Terminal::Hash160(hash) => {
-                Some(SatisfiableItem::Hash160Preimage { hash: *hash }.into())
-            }
-            Terminal::Multi(k, pks) | Terminal::MultiA(k, pks) => {
-                Policy::make_multisig::<Ctx>(pks, signers, build_sat, *k, false, secp)?
-            }
-            // Identities
-            Terminal::Alt(inner)
-            | Terminal::Swap(inner)
-            | Terminal::Check(inner)
-            | Terminal::DupIf(inner)
-            | Terminal::Verify(inner)
-            | Terminal::NonZero(inner)
-            | Terminal::ZeroNotEqual(inner) => inner.extract_policy(signers, build_sat, secp)?,
-            // Complex policies
-            Terminal::AndV(a, b) | Terminal::AndB(a, b) => Policy::make_and(
-                a.extract_policy(signers, build_sat, secp)?,
-                b.extract_policy(signers, build_sat, secp)?,
-            )?,
-            Terminal::AndOr(x, y, z) => Policy::make_or(
-                Policy::make_and(
-                    x.extract_policy(signers, build_sat, secp)?,
-                    y.extract_policy(signers, build_sat, secp)?,
-                )?,
-                z.extract_policy(signers, build_sat, secp)?,
-            )?,
-            Terminal::OrB(a, b)
-            | Terminal::OrD(a, b)
-            | Terminal::OrC(a, b)
-            | Terminal::OrI(a, b) => Policy::make_or(
-                a.extract_policy(signers, build_sat, secp)?,
-                b.extract_policy(signers, build_sat, secp)?,
-            )?,
-            Terminal::Thresh(k, nodes) => {
-                let mut threshold = *k;
-                let mapped: Vec<_> = nodes
-                    .iter()
-                    .map(|n| n.extract_policy(signers, build_sat, secp))
-                    .collect::<Result<Vec<_>, _>>()?
-                    .into_iter()
-                    .flatten()
-                    .collect();
-
-                if mapped.len() < nodes.len() {
-                    threshold = match threshold.checked_sub(nodes.len() - mapped.len()) {
-                        None => return Ok(None),
-                        Some(x) => x,
-                    };
-                }
-
-                Policy::make_thresh(mapped, threshold)?
-            }
-
-            // Unsupported
-            Terminal::RawPkH(_) => None,
-        })
-    }
-}
-
-fn psbt_inputs_sat(psbt: &Psbt) -> impl Iterator<Item = PsbtInputSatisfier> {
-    (0..psbt.inputs.len()).map(move |i| PsbtInputSatisfier::new(psbt, i))
-}
-
-/// Options to build the satisfaction field in the policy
-#[derive(Debug, Clone, Copy)]
-pub enum BuildSatisfaction<'a> {
-    /// Don't generate `satisfaction` field
-    None,
-    /// Analyze the given PSBT to check for existing signatures
-    Psbt(&'a Psbt),
-    /// Like `Psbt` variant and also check for expired timelocks
-    PsbtTimelocks {
-        /// Given PSBT
-        psbt: &'a Psbt,
-        /// Current blockchain height
-        current_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
-        input_max_height: u32,
-    },
-}
-impl<'a> BuildSatisfaction<'a> {
-    fn psbt(&self) -> Option<&'a Psbt> {
-        match self {
-            BuildSatisfaction::None => None,
-            BuildSatisfaction::Psbt(psbt) => Some(psbt),
-            BuildSatisfaction::PsbtTimelocks { psbt, .. } => Some(psbt),
-        }
-    }
-}
-
-impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
-    fn extract_policy(
-        &self,
-        signers: &SignersContainer,
-        build_sat: BuildSatisfaction,
-        secp: &SecpCtx,
-    ) -> Result<Option<Policy>, Error> {
-        fn make_sortedmulti<Ctx: ScriptContext + 'static>(
-            keys: &SortedMultiVec<DescriptorPublicKey, Ctx>,
-            signers: &SignersContainer,
-            build_sat: BuildSatisfaction,
-            secp: &SecpCtx,
-        ) -> Result<Option<Policy>, Error> {
-            Ok(Policy::make_multisig::<Ctx>(
-                keys.pks.as_ref(),
-                signers,
-                build_sat,
-                keys.k,
-                true,
-                secp,
-            )?)
-        }
-
-        match self {
-            Descriptor::Pkh(pk) => Ok(Some(miniscript::Legacy::make_signature(
-                pk.as_inner(),
-                signers,
-                build_sat,
-                secp,
-            ))),
-            Descriptor::Wpkh(pk) => Ok(Some(miniscript::Segwitv0::make_signature(
-                pk.as_inner(),
-                signers,
-                build_sat,
-                secp,
-            ))),
-            Descriptor::Sh(sh) => match sh.as_inner() {
-                ShInner::Wpkh(pk) => Ok(Some(miniscript::Segwitv0::make_signature(
-                    pk.as_inner(),
-                    signers,
-                    build_sat,
-                    secp,
-                ))),
-                ShInner::Ms(ms) => Ok(ms.extract_policy(signers, build_sat, secp)?),
-                ShInner::SortedMulti(ref keys) => make_sortedmulti(keys, signers, build_sat, secp),
-                ShInner::Wsh(wsh) => match wsh.as_inner() {
-                    WshInner::Ms(ms) => Ok(ms.extract_policy(signers, build_sat, secp)?),
-                    WshInner::SortedMulti(ref keys) => {
-                        make_sortedmulti(keys, signers, build_sat, secp)
-                    }
-                },
-            },
-            Descriptor::Wsh(wsh) => match wsh.as_inner() {
-                WshInner::Ms(ms) => Ok(ms.extract_policy(signers, build_sat, secp)?),
-                WshInner::SortedMulti(ref keys) => make_sortedmulti(keys, signers, build_sat, secp),
-            },
-            Descriptor::Bare(ms) => Ok(ms.as_inner().extract_policy(signers, build_sat, secp)?),
-            Descriptor::Tr(tr) => {
-                // If there's no tap tree, treat this as a single sig, otherwise build a `Thresh`
-                // node with threshold = 1 and the key spend signature plus all the tree leaves
-                let key_spend_sig =
-                    miniscript::Tap::make_signature(tr.internal_key(), signers, build_sat, secp);
-
-                if tr.tap_tree().is_none() {
-                    Ok(Some(key_spend_sig))
-                } else {
-                    let mut items = vec![key_spend_sig];
-                    items.append(
-                        &mut tr
-                            .iter_scripts()
-                            .filter_map(|(_, ms)| {
-                                ms.extract_policy(signers, build_sat, secp).transpose()
-                            })
-                            .collect::<Result<Vec<_>, _>>()?,
-                    );
-
-                    Ok(Policy::make_thresh(items, 1)?)
-                }
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use crate::descriptor;
-    use crate::descriptor::{ExtractPolicy, IntoWalletDescriptor};
-
-    use super::*;
-    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::bip32;
-    use bitcoin::secp256k1::Secp256k1;
-    use bitcoin::Network;
-    use core::str::FromStr;
-
-    const TPRV0_STR:&str = "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf";
-    const TPRV1_STR:&str = "tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N";
-
-    const PATH: &str = "m/44'/1'/0'/0";
-
-    fn setup_keys<Ctx: ScriptContext>(
-        tprv: &str,
-        path: &str,
-        secp: &SecpCtx,
-    ) -> (DescriptorKey<Ctx>, DescriptorKey<Ctx>, Fingerprint) {
-        let path = bip32::DerivationPath::from_str(path).unwrap();
-        let tprv = bip32::Xpriv::from_str(tprv).unwrap();
-        let tpub = bip32::Xpub::from_priv(secp, &tprv);
-        let fingerprint = tprv.fingerprint(secp);
-        let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap();
-        let pubkey = (tpub, path).into_descriptor_key().unwrap();
-
-        (prvkey, pubkey, fingerprint)
-    }
-
-    // test ExtractPolicy trait for simple descriptors; wpkh(), sh(multi())
-
-    #[test]
-    fn test_extract_policy_for_wpkh() {
-        let secp = Secp256k1::new();
-
-        let (prvkey, pubkey, fingerprint) = setup_keys(TPRV0_STR, PATH, &secp);
-        let desc = descriptor!(wpkh(pubkey)).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint);
-        assert_matches!(&policy.contribution, Satisfaction::None);
-
-        let desc = descriptor!(wpkh(prvkey)).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint);
-        assert_matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv.is_none() && condition.timelock.is_none());
-    }
-
-    // 2 pub keys descriptor, required 2 prv keys
-    #[test]
-    fn test_extract_policy_for_sh_multi_partial_0of2() {
-        let secp = Secp256k1::new();
-        let (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
-        let (_prvkey1, pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
-        let desc = descriptor!(sh(multi(2, pubkey0, pubkey1))).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
-            && keys[0] == PkOrF::Fingerprint(fingerprint0)
-            && keys[1] == PkOrF::Fingerprint(fingerprint1)
-        );
-        // TODO should this be "Satisfaction::None" since we have no prv keys?
-        // TODO should items and conditions not be empty?
-        assert_matches!(&policy.contribution, Satisfaction::Partial { n, m, items, conditions, ..} if n == &2usize
-            && m == &2usize
-            && items.is_empty()
-            && conditions.is_empty()
-        );
-    }
-
-    // 1 prv and 1 pub key descriptor, required 2 prv keys
-    #[test]
-    fn test_extract_policy_for_sh_multi_partial_1of2() {
-        let secp = Secp256k1::new();
-        let (prvkey0, _pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
-        let (_prvkey1, pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
-        let desc = descriptor!(sh(multi(2, prvkey0, pubkey1))).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-        assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
-            && keys[0] == PkOrF::Fingerprint(fingerprint0)
-            && keys[1] == PkOrF::Fingerprint(fingerprint1)
-        );
-
-        assert_matches!(&policy.contribution, Satisfaction::Partial { n, m, items, conditions, ..} if n == &2usize
-             && m == &2usize
-             && items.len() == 1
-             && conditions.contains_key(&0)
-        );
-    }
-
-    // 1 prv and 1 pub key descriptor, required 1 prv keys
-    #[test]
-    #[ignore] // see https://github.com/bitcoindevkit/bdk/issues/225
-    fn test_extract_policy_for_sh_multi_complete_1of2() {
-        let secp = Secp256k1::new();
-
-        let (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
-        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
-        let desc = descriptor!(sh(multi(1, pubkey0, prvkey1))).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
-            && keys[0] == PkOrF::Fingerprint(fingerprint0)
-            && keys[1] == PkOrF::Fingerprint(fingerprint1)
-        );
-        assert_matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2
-             && m == &1
-             && items.len() == 2
-             && conditions.contains_key(&vec![0])
-             && conditions.contains_key(&vec![1])
-        );
-    }
-
-    // 2 prv keys descriptor, required 2 prv keys
-    #[test]
-    fn test_extract_policy_for_sh_multi_complete_2of2() {
-        let secp = Secp256k1::new();
-
-        let (prvkey0, _pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
-        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
-        let desc = descriptor!(sh(multi(2, prvkey0, prvkey1))).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
-            && keys[0] == PkOrF::Fingerprint(fingerprint0)
-            && keys[1] == PkOrF::Fingerprint(fingerprint1)
-        );
-
-        assert_matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2
-             && m == &2
-             && items.len() == 2
-             && conditions.contains_key(&vec![0,1])
-        );
-    }
-
-    // test ExtractPolicy trait with extended and single keys
-
-    #[test]
-    fn test_extract_policy_for_single_wpkh() {
-        let secp = Secp256k1::new();
-
-        let (prvkey, pubkey, fingerprint) = setup_keys(TPRV0_STR, PATH, &secp);
-        let desc = descriptor!(wpkh(pubkey)).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint);
-        assert_matches!(&policy.contribution, Satisfaction::None);
-
-        let desc = descriptor!(wpkh(prvkey)).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == fingerprint);
-        assert_matches!(policy.contribution, Satisfaction::Complete {condition} if condition.csv.is_none() && condition.timelock.is_none());
-    }
-
-    // single key, 1 prv and 1 pub key descriptor, required 1 prv keys
-    #[test]
-    #[ignore] // see https://github.com/bitcoindevkit/bdk/issues/225
-    fn test_extract_policy_for_single_wsh_multi_complete_1of2() {
-        let secp = Secp256k1::new();
-
-        let (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
-        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
-        let desc = descriptor!(sh(multi(1, pubkey0, prvkey1))).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(policy.item, Multisig { keys, threshold } if threshold == 1
-            && keys[0] == PkOrF::Fingerprint(fingerprint0)
-            && keys[1] == PkOrF::Fingerprint(fingerprint1)
-        );
-        assert_matches!(policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == 2
-             && m == 1
-             && items.len() == 2
-             && conditions.contains_key(&vec![0])
-             && conditions.contains_key(&vec![1])
-        );
-    }
-
-    // test ExtractPolicy trait with descriptors containing timelocks in a thresh()
-
-    #[test]
-    #[ignore] // see https://github.com/bitcoindevkit/bdk/issues/225
-    fn test_extract_policy_for_wsh_multi_timelock() {
-        let secp = Secp256k1::new();
-
-        let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
-        let (_prvkey1, pubkey1, _fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
-        let sequence = 50;
-        #[rustfmt::skip]
-        let desc = descriptor!(wsh(thresh(
-            2,
-            pk(prvkey0),
-            s:pk(pubkey1),
-            s:d:v:older(sequence)
-        )))
-        .unwrap();
-
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(&policy.item, Thresh { items, threshold } if items.len() == 3 && threshold == &2);
-
-        assert_matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &3
-             && m == &2
-             && items.len() == 3
-             && conditions.get(&vec![0,1]).unwrap().iter().next().unwrap().csv.is_none()
-             && conditions.get(&vec![0,2]).unwrap().iter().next().unwrap().csv == Some(Sequence(sequence))
-             && conditions.get(&vec![1,2]).unwrap().iter().next().unwrap().csv == Some(Sequence(sequence))
-        );
-    }
-
-    // - mixed timelocks should fail
-
-    #[test]
-    #[ignore]
-    fn test_extract_policy_for_wsh_mixed_timelocks() {
-        let secp = Secp256k1::new();
-        let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
-        let locktime_threshold = 500000000; // if less than this means block number, else block time in seconds
-        let locktime_blocks = 100;
-        let locktime_seconds = locktime_blocks + locktime_threshold;
-        let desc = descriptor!(sh(and_v(
-            v: pk(prvkey0),
-            and_v(v: after(locktime_seconds), after(locktime_blocks))
-        )))
-        .unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        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?
-    }
-
-    // - multiple timelocks of the same type should be correctly merged together
-    #[test]
-    #[ignore]
-    fn test_extract_policy_for_multiple_same_timelocks() {
-        let secp = Secp256k1::new();
-        let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
-        let locktime_blocks0 = 100;
-        let locktime_blocks1 = 200;
-        let desc = descriptor!(sh(and_v(
-            v: pk(prvkey0),
-            and_v(v: after(locktime_blocks0), after(locktime_blocks1))
-        )))
-        .unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        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?
-        let (prvkey1, _pubkey1, _fingerprint1) = setup_keys(TPRV0_STR, PATH, &secp);
-        let locktime_seconds0 = 500000100;
-        let locktime_seconds1 = 500000200;
-        let desc = descriptor!(sh(and_v(
-            v: pk(prvkey1),
-            and_v(v: after(locktime_seconds0), after(locktime_seconds1))
-        )))
-        .unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-        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?
-    }
-
-    #[test]
-    fn test_get_condition_multisig() {
-        let secp = Secp256k1::new();
-
-        let (_, pk0, _) = setup_keys(TPRV0_STR, PATH, &secp);
-        let (_, pk1, _) = setup_keys(TPRV1_STR, PATH, &secp);
-
-        let desc = descriptor!(wsh(multi(1, pk0, pk1))).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        // no args, choose the default
-        let no_args = policy.get_condition(&vec![].into_iter().collect());
-        assert_eq!(no_args, Ok(Condition::default()));
-
-        // enough args
-        let eq_thresh =
-            policy.get_condition(&vec![(policy.id.clone(), vec![0])].into_iter().collect());
-        assert_eq!(eq_thresh, Ok(Condition::default()));
-
-        // more args, it doesn't really change anything
-        let gt_thresh =
-            policy.get_condition(&vec![(policy.id.clone(), vec![0, 1])].into_iter().collect());
-        assert_eq!(gt_thresh, Ok(Condition::default()));
-
-        // not enough args, error
-        let lt_thresh =
-            policy.get_condition(&vec![(policy.id.clone(), vec![])].into_iter().collect());
-        assert_eq!(
-            lt_thresh,
-            Err(PolicyError::NotEnoughItemsSelected(policy.id.clone()))
-        );
-
-        // index out of range
-        let out_of_range =
-            policy.get_condition(&vec![(policy.id.clone(), vec![5])].into_iter().collect());
-        assert_eq!(out_of_range, Err(PolicyError::IndexOutOfRange(5)));
-    }
-
-    const ALICE_TPRV_STR:&str = "tprv8ZgxMBicQKsPf6T5X327efHnvJDr45Xnb8W4JifNWtEoqXu9MRYS4v1oYe6DFcMVETxy5w3bqpubYRqvcVTqovG1LifFcVUuJcbwJwrhYzP";
-    const BOB_TPRV_STR:&str = "tprv8ZgxMBicQKsPeinZ155cJAn117KYhbaN6MV3WeG6sWhxWzcvX1eg1awd4C9GpUN1ncLEM2rzEvunAg3GizdZD4QPPCkisTz99tXXB4wZArp";
-    const CAROL_TPRV_STR:&str = "tprv8ZgxMBicQKsPdC3CicFifuLCEyVVdXVUNYorxUWj3iGZ6nimnLAYAY9SYB7ib8rKzRxrCKFcEytCt6szwd2GHnGPRCBLAEAoSVDefSNk4Bt";
-    const ALICE_BOB_PATH: &str = "m/0'";
-
-    #[test]
-    fn test_extract_satisfaction() {
-        const ALICE_SIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAZb0njwT2wRS3AumaaP3yb7T4MxOePpSWih4Nq+jWChMAQAAAAD/////Af4lAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASuJJgAAAAAAACIAIERw5kTLo9DUH9QDJSClHQwPpC7VGJ+ZMDpa8U+2fzcYIgIDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42ZstHMEQCIBj0jLjUeVYXNQ6cqB+gbtvuKMjV54wSgWlm1cfcgpHVAiBa3DtC9l/1Mt4IDCvR7mmwQd3eAP/m5++81euhJNSrgQEBBUdSIQN4C2NhCT9V+7h1vb7ryHIwqNzfz6RaXmw/lAfwvjZmyyEC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhSriIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAAA";
-        const BOB_SIGNED_PSBT: &str =   "cHNidP8BAFMBAAAAAZb0njwT2wRS3AumaaP3yb7T4MxOePpSWih4Nq+jWChMAQAAAAD/////Af4lAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASuJJgAAAAAAACIAIERw5kTLo9DUH9QDJSClHQwPpC7VGJ+ZMDpa8U+2fzcYIgIC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhIMEUCIQD5zDtM5MwklurwJ5aW76RsO36Iqyu+6uMdVlhL6ws2GQIgesAiz4dbKS7UmhDsC/c1ezu0o6hp00UUtsCMfUZ4anYBAQVHUiEDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42ZsshAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIUq4iBgL4YT/L4um0jzGaJHqw5733wgbPJujHRB/Pj4FCXWeZiAwcLu4+AAAAgAAAAAAiBgN4C2NhCT9V+7h1vb7ryHIwqNzfz6RaXmw/lAfwvjZmywzJEXwuAAAAgAAAAAAAAA==";
-        const ALICE_BOB_SIGNED_PSBT: &str =   "cHNidP8BAFMBAAAAAZb0njwT2wRS3AumaaP3yb7T4MxOePpSWih4Nq+jWChMAQAAAAD/////Af4lAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASuJJgAAAAAAACIAIERw5kTLo9DUH9QDJSClHQwPpC7VGJ+ZMDpa8U+2fzcYIgIC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhIMEUCIQD5zDtM5MwklurwJ5aW76RsO36Iqyu+6uMdVlhL6ws2GQIgesAiz4dbKS7UmhDsC/c1ezu0o6hp00UUtsCMfUZ4anYBIgIDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42ZstHMEQCIBj0jLjUeVYXNQ6cqB+gbtvuKMjV54wSgWlm1cfcgpHVAiBa3DtC9l/1Mt4IDCvR7mmwQd3eAP/m5++81euhJNSrgQEBBUdSIQN4C2NhCT9V+7h1vb7ryHIwqNzfz6RaXmw/lAfwvjZmyyEC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhSriIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAEHAAEI2wQARzBEAiAY9Iy41HlWFzUOnKgfoG7b7ijI1eeMEoFpZtXH3IKR1QIgWtw7QvZf9TLeCAwr0e5psEHd3gD/5ufvvNXroSTUq4EBSDBFAiEA+cw7TOTMJJbq8CeWlu+kbDt+iKsrvurjHVZYS+sLNhkCIHrAIs+HWyku1JoQ7Av3NXs7tKOoadNFFLbAjH1GeGp2AUdSIQN4C2NhCT9V+7h1vb7ryHIwqNzfz6RaXmw/lAfwvjZmyyEC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhSrgAA";
-
-        let secp = Secp256k1::new();
-
-        let (prvkey_alice, _, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
-        let (prvkey_bob, _, _) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
-
-        let desc = descriptor!(wsh(multi(2, prvkey_alice, prvkey_bob))).unwrap();
-
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-
-        let addr = wallet_desc
-            .at_derivation_index(0)
-            .unwrap()
-            .address(Network::Testnet)
-            .unwrap();
-        assert_eq!(
-            "tb1qg3cwv3xt50gdg875qvjjpfgaps86gtk4rz0ejvp6ttc5ldnlxuvqlcn0xk",
-            addr.to_string()
-        );
-
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-
-        let psbt = Psbt::from_str(ALICE_SIGNED_PSBT).unwrap();
-
-        let policy_alice_psbt = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::Psbt(&psbt), &secp)
-            .unwrap()
-            .unwrap();
-        //println!("{}", serde_json::to_string(&policy_alice_psbt).unwrap());
-
-        assert_matches!(&policy_alice_psbt.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &2
-             && m == &2
-             && items == &vec![0]
-        );
-
-        let psbt = Psbt::from_str(BOB_SIGNED_PSBT).unwrap();
-        let policy_bob_psbt = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::Psbt(&psbt), &secp)
-            .unwrap()
-            .unwrap();
-        //println!("{}", serde_json::to_string(&policy_bob_psbt).unwrap());
-
-        assert_matches!(&policy_bob_psbt.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &2
-             && m == &2
-             && items == &vec![1]
-        );
-
-        let psbt = Psbt::from_str(ALICE_BOB_SIGNED_PSBT).unwrap();
-        let policy_alice_bob_psbt = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::Psbt(&psbt), &secp)
-            .unwrap()
-            .unwrap();
-        assert_matches!(&policy_alice_bob_psbt.satisfaction, Satisfaction::PartialComplete { n, m, items, .. } if n == &2
-             && m == &2
-             && items == &vec![0, 1]
-        );
-    }
-
-    #[test]
-    fn test_extract_satisfaction_timelock() {
-        //const PSBT_POLICY_CONSIDER_TIMELOCK_NOT_EXPIRED: &str = "cHNidP8BAFMBAAAAAdld52uJFGT7Yde0YZdSVh2vL020Zm2exadH5R4GSNScAAAAAAD/////ATrcAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASvI3AAAAAAAACIAILhzvvcBzw/Zfnc9ispRK0PCahxn1F6RHXTZAmw5tqNPAQVSdmNSsmlofCEDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42Zsusk3whAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIrJNShyIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAAA";
-        const PSBT_POLICY_CONSIDER_TIMELOCK_EXPIRED:     &str = "cHNidP8BAFMCAAAAAdld52uJFGT7Yde0YZdSVh2vL020Zm2exadH5R4GSNScAAAAAAACAAAAATrcAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASvI3AAAAAAAACIAILhzvvcBzw/Zfnc9ispRK0PCahxn1F6RHXTZAmw5tqNPAQVSdmNSsmlofCEDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42Zsusk3whAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIrJNShyIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAAA";
-        const PSBT_POLICY_CONSIDER_TIMELOCK_EXPIRED_SIGNED: &str ="cHNidP8BAFMCAAAAAdld52uJFGT7Yde0YZdSVh2vL020Zm2exadH5R4GSNScAAAAAAACAAAAATrcAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASvI3AAAAAAAACIAILhzvvcBzw/Zfnc9ispRK0PCahxn1F6RHXTZAmw5tqNPIgIDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42ZstIMEUCIQCtZxNm6H3Ux3pnc64DSpgohMdBj+57xhFHcURYt2BpPAIgG3OnI7bcj/3GtWX1HHyYGSI7QGa/zq5YnsmK1Cw29NABAQVSdmNSsmlofCEDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42Zsusk3whAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIrJNShyIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAEHAAEIoAQASDBFAiEArWcTZuh91Md6Z3OuA0qYKITHQY/ue8YRR3FEWLdgaTwCIBtzpyO23I/9xrVl9Rx8mBkiO0Bmv86uWJ7JitQsNvTQAQEBUnZjUrJpaHwhA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLrJN8IQL4YT/L4um0jzGaJHqw5733wgbPJujHRB/Pj4FCXWeZiKyTUocAAA==";
-
-        let secp = Secp256k1::new();
-
-        let (prvkey_alice, _, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
-        let (prvkey_bob, _, _) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
-
-        let desc =
-            descriptor!(wsh(thresh(2,n:d:v:older(2),s:pk(prvkey_alice),s:pk(prvkey_bob)))).unwrap();
-
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-
-        let addr = wallet_desc
-            .at_derivation_index(0)
-            .unwrap()
-            .address(Network::Testnet)
-            .unwrap();
-        assert_eq!(
-            "tb1qsydsey4hexagwkvercqsmes6yet0ndkyt6uzcphtqnygjd8hmzmsfxrv58",
-            addr.to_string()
-        );
-
-        let psbt = Psbt::from_str(PSBT_POLICY_CONSIDER_TIMELOCK_EXPIRED).unwrap();
-
-        let build_sat = BuildSatisfaction::PsbtTimelocks {
-            psbt: &psbt,
-            current_height: 10,
-            input_max_height: 9,
-        };
-
-        let policy = wallet_desc
-            .extract_policy(&signers_container, build_sat, &secp)
-            .unwrap()
-            .unwrap();
-        assert_matches!(&policy.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &3
-             && m == &2
-             && items.is_empty()
-        );
-        //println!("{}", serde_json::to_string(&policy).unwrap());
-
-        let build_sat_expired = BuildSatisfaction::PsbtTimelocks {
-            psbt: &psbt,
-            current_height: 12,
-            input_max_height: 9,
-        };
-
-        let policy_expired = wallet_desc
-            .extract_policy(&signers_container, build_sat_expired, &secp)
-            .unwrap()
-            .unwrap();
-        assert_matches!(&policy_expired.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &3
-             && m == &2
-             && items == &vec![0]
-        );
-        //println!("{}", serde_json::to_string(&policy_expired).unwrap());
-
-        let psbt_signed = Psbt::from_str(PSBT_POLICY_CONSIDER_TIMELOCK_EXPIRED_SIGNED).unwrap();
-
-        let build_sat_expired_signed = BuildSatisfaction::PsbtTimelocks {
-            psbt: &psbt_signed,
-            current_height: 12,
-            input_max_height: 9,
-        };
-
-        let policy_expired_signed = wallet_desc
-            .extract_policy(&signers_container, build_sat_expired_signed, &secp)
-            .unwrap()
-            .unwrap();
-        assert_matches!(&policy_expired_signed.satisfaction, Satisfaction::PartialComplete { n, m, items, .. } if n == &3
-             && m == &2
-             && items == &vec![0, 1]
-        );
-        //println!("{}", serde_json::to_string(&policy_expired_signed).unwrap());
-    }
-
-    #[test]
-    fn test_extract_pkh() {
-        let secp = Secp256k1::new();
-
-        let (prvkey_alice, _, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
-        let (prvkey_bob, _, _) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
-        let (prvkey_carol, _, _) = setup_keys(CAROL_TPRV_STR, ALICE_BOB_PATH, &secp);
-
-        let desc = descriptor!(wsh(c: andor(
-            pk(prvkey_alice),
-            pk_k(prvkey_bob),
-            pk_h(prvkey_carol),
-        )))
-        .unwrap();
-
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-
-        let policy = wallet_desc.extract_policy(&signers_container, BuildSatisfaction::None, &secp);
-        assert!(policy.is_ok());
-    }
-
-    #[test]
-    fn test_extract_tr_key_spend() {
-        let secp = Secp256k1::new();
-
-        let (prvkey, _, fingerprint) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
-
-        let desc = descriptor!(tr(prvkey)).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap();
-        assert_eq!(
-            policy,
-            Some(Policy {
-                id: "48u0tz0n".to_string(),
-                item: SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(fingerprint)),
-                satisfaction: Satisfaction::None,
-                contribution: Satisfaction::Complete {
-                    condition: Condition::default()
-                }
-            })
-        );
-    }
-
-    #[test]
-    fn test_extract_tr_script_spend() {
-        let secp = Secp256k1::new();
-
-        let (alice_prv, _, alice_fing) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
-        let (_, bob_pub, bob_fing) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
-
-        let desc = descriptor!(tr(bob_pub, pk(alice_prv))).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
-
-        let policy = wallet_desc
-            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(policy.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2);
-        assert_matches!(policy.contribution, Satisfaction::PartialComplete { n: 2, m: 1, items, .. } if items == vec![1]);
-
-        let alice_sig = SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(alice_fing));
-        let bob_sig = SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(bob_fing));
-
-        let thresh_items = match policy.item {
-            SatisfiableItem::Thresh { items, .. } => items,
-            _ => unreachable!(),
-        };
-
-        assert_eq!(thresh_items[0].item, bob_sig);
-        assert_eq!(thresh_items[1].item, alice_sig);
-    }
-
-    #[test]
-    fn test_extract_tr_satisfaction_key_spend() {
-        const UNSIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAUKgMCqtGLSiGYhsTols2UJ/VQQgQi/SXO38uXs2SahdAQAAAAD/////ARyWmAAAAAAAF6kU4R3W8CnGzZcSsaovTYu0X8vHt3WHAAAAAAABASuAlpgAAAAAACJRIEiEBFjbZa1xdjLfFjrKzuC1F1LeRyI/gL6IuGKNmUuSIRYnkGTDxwXMHP32fkDFoGJY28trxbkkVgR2z7jZa2pOJA0AyRF8LgAAAIADAAAAARcgJ5Bkw8cFzBz99n5AxaBiWNvLa8W5JFYEds+42WtqTiQAAA==";
-        const SIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAUKgMCqtGLSiGYhsTols2UJ/VQQgQi/SXO38uXs2SahdAQAAAAD/////ARyWmAAAAAAAF6kU4R3W8CnGzZcSsaovTYu0X8vHt3WHAAAAAAABASuAlpgAAAAAACJRIEiEBFjbZa1xdjLfFjrKzuC1F1LeRyI/gL6IuGKNmUuSARNAIsRvARpRxuyQosVA7guRQT9vXr+S25W2tnP2xOGBsSgq7A4RL8yrbvwDmNlWw9R0Nc/6t+IsyCyy7dD/lbUGgyEWJ5Bkw8cFzBz99n5AxaBiWNvLa8W5JFYEds+42WtqTiQNAMkRfC4AAACAAwAAAAEXICeQZMPHBcwc/fZ+QMWgYljby2vFuSRWBHbPuNlrak4kAAA=";
-
-        let unsigned_psbt = Psbt::from_str(UNSIGNED_PSBT).unwrap();
-        let signed_psbt = Psbt::from_str(SIGNED_PSBT).unwrap();
-
-        let secp = Secp256k1::new();
-
-        let (_, pubkey, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
-
-        let desc = descriptor!(tr(pubkey)).unwrap();
-        let (wallet_desc, _) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-
-        let policy_unsigned = wallet_desc
-            .extract_policy(
-                &SignersContainer::default(),
-                BuildSatisfaction::Psbt(&unsigned_psbt),
-                &secp,
-            )
-            .unwrap()
-            .unwrap();
-        let policy_signed = wallet_desc
-            .extract_policy(
-                &SignersContainer::default(),
-                BuildSatisfaction::Psbt(&signed_psbt),
-                &secp,
-            )
-            .unwrap()
-            .unwrap();
-
-        assert_eq!(policy_unsigned.satisfaction, Satisfaction::None);
-        assert_eq!(
-            policy_signed.satisfaction,
-            Satisfaction::Complete {
-                condition: Default::default()
-            }
-        );
-    }
-
-    #[test]
-    fn test_extract_tr_satisfaction_script_spend() {
-        const UNSIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAWZalxaErOL7P3WPIUc8DsjgE68S+ww+uqiqEI2SAwlPAAAAAAD/////AQiWmAAAAAAAF6kU4R3W8CnGzZcSsaovTYu0X8vHt3WHAAAAAAABASuAlpgAAAAAACJRINa6bLPZwp3/CYWoxyI3mLYcSC5f9LInAMUng94nspa2IhXBgiPY+kcolS1Hp0niOK/+7VHz6F+nsz8JVxnzWzkgToYjIHhGyuexxtRVKevRx4YwWR/W0r7LPHt6oS6DLlzyuYQarMAhFnhGyuexxtRVKevRx4YwWR/W0r7LPHt6oS6DLlzyuYQaLQH2onWFc3UR6I9ZhuHVeJCi5LNAf4APVd7mHn4BhdViHRwu7j4AAACAAgAAACEWgiPY+kcolS1Hp0niOK/+7VHz6F+nsz8JVxnzWzkgToYNAMkRfC4AAACAAgAAAAEXIIIj2PpHKJUtR6dJ4jiv/u1R8+hfp7M/CVcZ81s5IE6GARgg9qJ1hXN1EeiPWYbh1XiQouSzQH+AD1Xe5h5+AYXVYh0AAA==";
-        const SIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAWZalxaErOL7P3WPIUc8DsjgE68S+ww+uqiqEI2SAwlPAAAAAAD/////AQiWmAAAAAAAF6kU4R3W8CnGzZcSsaovTYu0X8vHt3WHAAAAAAABASuAlpgAAAAAACJRINa6bLPZwp3/CYWoxyI3mLYcSC5f9LInAMUng94nspa2AQcAAQhCAUALcP9w/+Ddly9DWdhHTnQ9uCDWLPZjR6vKbKePswW2Ee6W5KNfrklus/8z98n7BQ1U4vADHk0FbadeeL8rrbHlARNAC3D/cP/g3ZcvQ1nYR050Pbgg1iz2Y0erymynj7MFthHuluSjX65JbrP/M/fJ+wUNVOLwAx5NBW2nXni/K62x5UEUeEbK57HG1FUp69HHhjBZH9bSvss8e3qhLoMuXPK5hBr2onWFc3UR6I9ZhuHVeJCi5LNAf4APVd7mHn4BhdViHUAXNmWieJ80Fs+PMa2C186YOBPZbYG/ieEUkagMwzJ788SoCucNdp5wnxfpuJVygFhglDrXGzujFtC82PrMohwuIhXBgiPY+kcolS1Hp0niOK/+7VHz6F+nsz8JVxnzWzkgToYjIHhGyuexxtRVKevRx4YwWR/W0r7LPHt6oS6DLlzyuYQarMAhFnhGyuexxtRVKevRx4YwWR/W0r7LPHt6oS6DLlzyuYQaLQH2onWFc3UR6I9ZhuHVeJCi5LNAf4APVd7mHn4BhdViHRwu7j4AAACAAgAAACEWgiPY+kcolS1Hp0niOK/+7VHz6F+nsz8JVxnzWzkgToYNAMkRfC4AAACAAgAAAAEXIIIj2PpHKJUtR6dJ4jiv/u1R8+hfp7M/CVcZ81s5IE6GARgg9qJ1hXN1EeiPWYbh1XiQouSzQH+AD1Xe5h5+AYXVYh0AAA==";
-
-        let unsigned_psbt = Psbt::from_str(UNSIGNED_PSBT).unwrap();
-        let signed_psbt = Psbt::from_str(SIGNED_PSBT).unwrap();
-
-        let secp = Secp256k1::new();
-
-        let (_, alice_pub, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
-        let (_, bob_pub, _) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
-
-        let desc = descriptor!(tr(bob_pub, pk(alice_pub))).unwrap();
-        let (wallet_desc, _) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-
-        let policy_unsigned = wallet_desc
-            .extract_policy(
-                &SignersContainer::default(),
-                BuildSatisfaction::Psbt(&unsigned_psbt),
-                &secp,
-            )
-            .unwrap()
-            .unwrap();
-        let policy_signed = wallet_desc
-            .extract_policy(
-                &SignersContainer::default(),
-                BuildSatisfaction::Psbt(&signed_psbt),
-                &secp,
-            )
-            .unwrap()
-            .unwrap();
-
-        assert_matches!(policy_unsigned.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2);
-        assert_matches!(policy_unsigned.satisfaction, Satisfaction::Partial { n: 2, m: 1, items, .. } if items.is_empty());
-
-        assert_matches!(policy_signed.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2);
-        assert_matches!(policy_signed.satisfaction, Satisfaction::PartialComplete { n: 2, m: 1, items, .. } if items == vec![0, 1]);
-
-        let satisfied_items = match policy_signed.item {
-            SatisfiableItem::Thresh { items, .. } => items,
-            _ => unreachable!(),
-        };
-
-        assert_eq!(
-            satisfied_items[0].satisfaction,
-            Satisfaction::Complete {
-                condition: Default::default()
-            }
-        );
-        assert_eq!(
-            satisfied_items[1].satisfaction,
-            Satisfaction::Complete {
-                condition: Default::default()
-            }
-        );
-    }
-}
-
-
\ No newline at end of file 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 deleted file mode 100644 index 15a50868fd..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/template.rs.html +++ /dev/null @@ -1,1973 +0,0 @@ -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
-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
-
// 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.
-
-//! 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.
-
-use bitcoin::bip32;
-use bitcoin::Network;
-
-use miniscript::{Legacy, Segwitv0, Tap};
-
-use super::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap};
-use crate::descriptor::DescriptorError;
-use crate::keys::{DerivableKey, IntoDescriptorKey, ValidNetworks};
-use crate::wallet::utils::SecpCtx;
-use crate::{descriptor, KeychainKind};
-
-/// Type alias for the return type of [`DescriptorTemplate`], [`descriptor!`](crate::descriptor!) and others
-pub type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);
-
-/// Trait for descriptor templates that can be built into a full descriptor
-///
-/// Since [`IntoWalletDescriptor`] is implemented for any [`DescriptorTemplate`], they can also be
-/// passed directly to the [`Wallet`](crate::Wallet) constructor.
-///
-/// ## Example
-///
-/// ```
-/// use bdk::descriptor::error::Error as DescriptorError;
-/// use bdk::keys::{IntoDescriptorKey, KeyError};
-/// use bdk::miniscript::Legacy;
-/// use bdk::template::{DescriptorTemplate, DescriptorTemplateOut};
-/// use bitcoin::Network;
-///
-/// struct MyP2PKH<K: IntoDescriptorKey<Legacy>>(K);
-///
-/// impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
-///     fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-///         Ok(bdk::descriptor!(pkh(self.0))?)
-///     }
-/// }
-/// ```
-pub trait DescriptorTemplate {
-    /// Build the complete descriptor
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError>;
-}
-
-/// Turns a [`DescriptorTemplate`] into a valid wallet descriptor by calling its
-/// [`build`](DescriptorTemplate::build) method
-impl<T: DescriptorTemplate> IntoWalletDescriptor for T {
-    fn into_wallet_descriptor(
-        self,
-        secp: &SecpCtx,
-        network: Network,
-    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
-        self.build(network)?.into_wallet_descriptor(secp, network)
-    }
-}
-
-/// P2PKH template. Expands to a descriptor `pkh(key)`
-///
-/// ## Example
-///
-/// ```
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::Wallet;
-/// # use bdk::KeychainKind;
-/// use bdk::template::P2Pkh;
-///
-/// let key =
-///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-/// let mut wallet = Wallet::new_no_persist(P2Pkh(key), None, Network::Testnet)?;
-///
-/// assert_eq!(
-///     wallet
-///         .next_unused_address(KeychainKind::External)?
-///         .to_string(),
-///     "mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"
-/// );
-/// # Ok::<_, Box<dyn std::error::Error>>(())
-/// ```
-pub struct P2Pkh<K: IntoDescriptorKey<Legacy>>(pub K);
-
-impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2Pkh<K> {
-    fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        descriptor!(pkh(self.0))
-    }
-}
-
-/// P2WPKH-P2SH template. Expands to a descriptor `sh(wpkh(key))`
-///
-/// ## Example
-///
-/// ```
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::Wallet;
-/// # use bdk::KeychainKind;
-/// use bdk::template::P2Wpkh_P2Sh;
-///
-/// let key =
-///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-/// let mut wallet = Wallet::new_no_persist(P2Wpkh_P2Sh(key), None, Network::Testnet)?;
-///
-/// assert_eq!(
-///     wallet
-///         .next_unused_address(KeychainKind::External)?
-///         .to_string(),
-///     "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
-/// );
-/// # Ok::<_, Box<dyn std::error::Error>>(())
-/// ```
-#[allow(non_camel_case_types)]
-pub struct P2Wpkh_P2Sh<K: IntoDescriptorKey<Segwitv0>>(pub K);
-
-impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh_P2Sh<K> {
-    fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        descriptor!(sh(wpkh(self.0)))
-    }
-}
-
-/// P2WPKH template. Expands to a descriptor `wpkh(key)`
-///
-/// ## Example
-///
-/// ```
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet};
-/// # use bdk::KeychainKind;
-/// use bdk::template::P2Wpkh;
-///
-/// let key =
-///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-/// let mut wallet = Wallet::new_no_persist(P2Wpkh(key), None, Network::Testnet)?;
-///
-/// assert_eq!(
-///     wallet
-///         .next_unused_address(KeychainKind::External)?
-///         .to_string(),
-///     "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
-/// );
-/// # Ok::<_, Box<dyn std::error::Error>>(())
-/// ```
-pub struct P2Wpkh<K: IntoDescriptorKey<Segwitv0>>(pub K);
-
-impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> {
-    fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        descriptor!(wpkh(self.0))
-    }
-}
-
-/// P2TR template. Expands to a descriptor `tr(key)`
-///
-/// ## Example
-///
-/// ```
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::Wallet;
-/// # use bdk::KeychainKind;
-/// use bdk::template::P2TR;
-///
-/// let key =
-///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
-/// let mut wallet = Wallet::new_no_persist(P2TR(key), None, Network::Testnet)?;
-///
-/// assert_eq!(
-///     wallet
-///         .next_unused_address(KeychainKind::External)?
-///         .to_string(),
-///     "tb1pvjf9t34fznr53u5tqhejz4nr69luzkhlvsdsdfq9pglutrpve2xq7hps46"
-/// );
-/// # Ok::<_, Box<dyn std::error::Error>>(())
-/// ```
-pub struct P2TR<K: IntoDescriptorKey<Tap>>(pub K);
-
-impl<K: IntoDescriptorKey<Tap>> DescriptorTemplate for P2TR<K> {
-    fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        descriptor!(tr(self.0))
-    }
-}
-
-/// 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 std::str::FromStr;
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet,  KeychainKind};
-/// use bdk::template::Bip44;
-///
-/// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let mut wallet = Wallet::new_no_persist(
-///     Bip44(key.clone(), KeychainKind::External),
-///     Some(Bip44(key, KeychainKind::Internal)),
-///     Network::Testnet,
-/// )?;
-///
-/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
-
-impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        P2Pkh(legacy::make_bipxx_private(44, self.0, self.1, network)?).build(network)
-    }
-}
-
-/// 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
-/// for the key.
-///
-/// ## Example
-///
-/// ```
-/// # use std::str::FromStr;
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet,  KeychainKind};
-/// use bdk::template::Bip44Public;
-///
-/// let key = bitcoin::bip32::Xpub::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
-/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-/// let mut wallet = Wallet::new_no_persist(
-///     Bip44Public(key.clone(), fingerprint, KeychainKind::External),
-///     Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
-///     Network::Testnet,
-/// )?;
-///
-/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
-
-impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        P2Pkh(legacy::make_bipxx_public(
-            44, self.0, self.1, self.2, network,
-        )?)
-        .build(network)
-    }
-}
-
-/// 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 std::str::FromStr;
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet,  KeychainKind};
-/// use bdk::template::Bip49;
-///
-/// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let mut wallet = Wallet::new_no_persist(
-///     Bip49(key.clone(), KeychainKind::External),
-///     Some(Bip49(key, KeychainKind::Internal)),
-///     Network::Testnet,
-/// )?;
-///
-/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
-
-impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        P2Wpkh_P2Sh(segwit_v0::make_bipxx_private(49, self.0, self.1, network)?).build(network)
-    }
-}
-
-/// 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
-/// for the key.
-///
-/// ## Example
-///
-/// ```
-/// # use std::str::FromStr;
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet,  KeychainKind};
-/// use bdk::template::Bip49Public;
-///
-/// let key = bitcoin::bip32::Xpub::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
-/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-/// let mut wallet = Wallet::new_no_persist(
-///     Bip49Public(key.clone(), fingerprint, KeychainKind::External),
-///     Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
-///     Network::Testnet,
-/// )?;
-///
-/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
-
-impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        P2Wpkh_P2Sh(segwit_v0::make_bipxx_public(
-            49, self.0, self.1, self.2, network,
-        )?)
-        .build(network)
-    }
-}
-
-/// 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 std::str::FromStr;
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet,  KeychainKind};
-/// use bdk::template::Bip84;
-///
-/// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let mut wallet = Wallet::new_no_persist(
-///     Bip84(key.clone(), KeychainKind::External),
-///     Some(Bip84(key, KeychainKind::Internal)),
-///     Network::Testnet,
-/// )?;
-///
-/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
-
-impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        P2Wpkh(segwit_v0::make_bipxx_private(84, self.0, self.1, network)?).build(network)
-    }
-}
-
-/// 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
-/// for the key.
-///
-/// ## Example
-///
-/// ```
-/// # use std::str::FromStr;
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet,  KeychainKind};
-/// use bdk::template::Bip84Public;
-///
-/// let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
-/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-/// let mut wallet = Wallet::new_no_persist(
-///     Bip84Public(key.clone(), fingerprint, KeychainKind::External),
-///     Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
-///     Network::Testnet,
-/// )?;
-///
-/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
-
-impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        P2Wpkh(segwit_v0::make_bipxx_public(
-            84, self.0, self.1, self.2, network,
-        )?)
-        .build(network)
-    }
-}
-
-/// BIP86 template. Expands to `tr(key/86'/{0,1}'/0'/{0,1}/*)`
-///
-/// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
-///
-/// See [`Bip86Public`] for a template that can work with a `xpub`/`tpub`.
-///
-/// ## Example
-///
-/// ```
-/// # use std::str::FromStr;
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet,  KeychainKind};
-/// use bdk::template::Bip86;
-///
-/// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
-/// let mut wallet = Wallet::new_no_persist(
-///     Bip86(key.clone(), KeychainKind::External),
-///     Some(Bip86(key, KeychainKind::Internal)),
-///     Network::Testnet,
-/// )?;
-///
-/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.to_string(), "tb1p5unlj09djx8xsjwe97269kqtxqpwpu2epeskgqjfk4lnf69v4tnqpp35qu");
-/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDCiHofpEs47kx358bPdJmTZHmCDqQ8qw32upCSxHrSEdeeBs2T5Mq6QMB2ukeMqhNBiyhosBvJErteVhfURPGXPv3qLJPw5MVpHUewsbP2m/0/*)#dkgvr5hm");
-/// # Ok::<_, Box<dyn std::error::Error>>(())
-/// ```
-pub struct Bip86<K: DerivableKey<Tap>>(pub K, pub KeychainKind);
-
-impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        P2TR(segwit_v1::make_bipxx_private(86, self.0, self.1, network)?).build(network)
-    }
-}
-
-/// BIP86 public template. Expands to `tr(key/{0,1}/*)`
-///
-/// This assumes that the key used has already been derived with `m/86'/0'/0'` for Mainnet or `m/86'/1'/0'` for Testnet.
-///
-/// This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
-///
-/// See [`Bip86`] for a template that does the full derivation, but requires private data
-/// for the key.
-///
-/// ## Example
-///
-/// ```
-/// # use std::str::FromStr;
-/// # use bdk::bitcoin::{PrivateKey, Network};
-/// # use bdk::{Wallet,  KeychainKind};
-/// use bdk::template::Bip86Public;
-///
-/// let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
-/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
-/// let mut wallet = Wallet::new_no_persist(
-///     Bip86Public(key.clone(), fingerprint, KeychainKind::External),
-///     Some(Bip86Public(key, fingerprint, KeychainKind::Internal)),
-///     Network::Testnet,
-/// )?;
-///
-/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.to_string(), "tb1pwjp9f2k5n0xq73ecuu0c5njvgqr3vkh7yaylmpqvsuuaafymh0msvcmh37");
-/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#2p65srku");
-/// # Ok::<_, Box<dyn std::error::Error>>(())
-/// ```
-pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
-
-impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86Public<K> {
-    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
-        P2TR(segwit_v1::make_bipxx_public(
-            86, self.0, self.1, self.2, network,
-        )?)
-        .build(network)
-    }
-}
-
-macro_rules! expand_make_bipxx {
-    ( $mod_name:ident, $ctx:ty ) => {
-        mod $mod_name {
-            use super::*;
-
-            pub(super) fn make_bipxx_private<K: DerivableKey<$ctx>>(
-                bip: u32,
-                key: K,
-                keychain: KeychainKind,
-                network: Network,
-            ) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
-                let mut derivation_path = alloc::vec::Vec::with_capacity(4);
-                derivation_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
-
-                match network {
-                    Network::Bitcoin => {
-                        derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
-                    }
-                    _ => {
-                        derivation_path.push(bip32::ChildNumber::from_hardened_idx(1)?);
-                    }
-                }
-                derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
-
-                match keychain {
-                    KeychainKind::External => {
-                        derivation_path.push(bip32::ChildNumber::from_normal_idx(0)?)
-                    }
-                    KeychainKind::Internal => {
-                        derivation_path.push(bip32::ChildNumber::from_normal_idx(1)?)
-                    }
-                };
-
-                let derivation_path: bip32::DerivationPath = derivation_path.into();
-
-                Ok((key, derivation_path))
-            }
-            pub(super) fn make_bipxx_public<K: DerivableKey<$ctx>>(
-                bip: u32,
-                key: K,
-                parent_fingerprint: bip32::Fingerprint,
-                keychain: KeychainKind,
-                network: Network,
-            ) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
-                let derivation_path: bip32::DerivationPath = match keychain {
-                    KeychainKind::External => vec![bip32::ChildNumber::from_normal_idx(0)?].into(),
-                    KeychainKind::Internal => vec![bip32::ChildNumber::from_normal_idx(1)?].into(),
-                };
-
-                let source_path = bip32::DerivationPath::from(vec![
-                    bip32::ChildNumber::from_hardened_idx(bip)?,
-                    match network {
-                        Network::Bitcoin => bip32::ChildNumber::from_hardened_idx(0)?,
-                        _ => bip32::ChildNumber::from_hardened_idx(1)?,
-                    },
-                    bip32::ChildNumber::from_hardened_idx(0)?,
-                ]);
-
-                Ok((key, (parent_fingerprint, source_path), derivation_path))
-            }
-        }
-    };
-}
-
-expand_make_bipxx!(legacy, Legacy);
-expand_make_bipxx!(segwit_v0, Segwitv0);
-expand_make_bipxx!(segwit_v1, Tap);
-
-#[cfg(test)]
-mod test {
-    // test existing descriptor templates, make sure they are expanded to the right descriptors
-
-    use alloc::{string::ToString, vec::Vec};
-    use core::str::FromStr;
-
-    use super::*;
-    use crate::descriptor::{DescriptorError, DescriptorMeta};
-    use crate::keys::ValidNetworks;
-    use assert_matches::assert_matches;
-    use miniscript::descriptor::{DescriptorPublicKey, KeyMap};
-    use miniscript::Descriptor;
-
-    // BIP44 `pkh(key/44'/{0,1}'/0'/{0,1}/*)`
-    #[test]
-    fn test_bip44_template_cointype() {
-        use bitcoin::bip32::ChildNumber::{self, Hardened};
-
-        let xprvkey = bitcoin::bip32::Xpriv::from_str("xprv9s21ZrQH143K2fpbqApQL69a4oKdGVnVN52R82Ft7d1pSqgKmajF62acJo3aMszZb6qQ22QsVECSFxvf9uyxFUvFYQMq3QbtwtRSMjLAhMf").unwrap();
-        assert_eq!(Network::Bitcoin, xprvkey.network);
-        let xdesc = Bip44(xprvkey, KeychainKind::Internal)
-            .build(Network::Bitcoin)
-            .unwrap();
-
-        if let ExtendedDescriptor::Pkh(pkh) = xdesc.0 {
-            let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().unwrap().into();
-            let purpose = path.first().unwrap();
-            assert_matches!(purpose, Hardened { index: 44 });
-            let coin_type = path.get(1).unwrap();
-            assert_matches!(coin_type, Hardened { index: 0 });
-        }
-
-        let tprvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-        assert_eq!(Network::Testnet, tprvkey.network);
-        let tdesc = Bip44(tprvkey, KeychainKind::Internal)
-            .build(Network::Testnet)
-            .unwrap();
-
-        if let ExtendedDescriptor::Pkh(pkh) = tdesc.0 {
-            let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().unwrap().into();
-            let purpose = path.first().unwrap();
-            assert_matches!(purpose, Hardened { index: 44 });
-            let coin_type = path.get(1).unwrap();
-            assert_matches!(coin_type, Hardened { index: 1 });
-        }
-    }
-
-    // verify template descriptor generates expected address(es)
-    fn check(
-        desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>,
-        is_witness: bool,
-        is_taproot: bool,
-        is_fixed: bool,
-        network: Network,
-        expected: &[&str],
-    ) {
-        let (desc, _key_map, _networks) = desc.unwrap();
-        assert_eq!(desc.is_witness(), is_witness);
-        assert_eq!(desc.is_taproot(), is_taproot);
-        assert_eq!(!desc.has_wildcard(), is_fixed);
-        for i in 0..expected.len() {
-            let index = i as u32;
-            let child_desc = if !desc.has_wildcard() {
-                desc.at_derivation_index(0).unwrap()
-            } else {
-                desc.at_derivation_index(index).unwrap()
-            };
-            let address = child_desc.address(network).unwrap();
-            assert_eq!(address.to_string(), *expected.get(i).unwrap());
-        }
-    }
-
-    // P2PKH
-    #[test]
-    fn test_p2ph_template() {
-        let prvkey =
-            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
-                .unwrap();
-        check(
-            P2Pkh(prvkey).build(Network::Bitcoin),
-            false,
-            false,
-            true,
-            Network::Regtest,
-            &["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"],
-        );
-
-        let pubkey = bitcoin::PublicKey::from_str(
-            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
-        )
-        .unwrap();
-        check(
-            P2Pkh(pubkey).build(Network::Bitcoin),
-            false,
-            false,
-            true,
-            Network::Regtest,
-            &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
-        );
-    }
-
-    // P2WPKH-P2SH `sh(wpkh(key))`
-    #[test]
-    fn test_p2wphp2sh_template() {
-        let prvkey =
-            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
-                .unwrap();
-        check(
-            P2Wpkh_P2Sh(prvkey).build(Network::Bitcoin),
-            true,
-            false,
-            true,
-            Network::Regtest,
-            &["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"],
-        );
-
-        let pubkey = bitcoin::PublicKey::from_str(
-            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
-        )
-        .unwrap();
-        check(
-            P2Wpkh_P2Sh(pubkey).build(Network::Bitcoin),
-            true,
-            false,
-            true,
-            Network::Regtest,
-            &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
-        );
-    }
-
-    // P2WPKH `wpkh(key)`
-    #[test]
-    fn test_p2wph_template() {
-        let prvkey =
-            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
-                .unwrap();
-        check(
-            P2Wpkh(prvkey).build(Network::Bitcoin),
-            true,
-            false,
-            true,
-            Network::Regtest,
-            &["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"],
-        );
-
-        let pubkey = bitcoin::PublicKey::from_str(
-            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
-        )
-        .unwrap();
-        check(
-            P2Wpkh(pubkey).build(Network::Bitcoin),
-            true,
-            false,
-            true,
-            Network::Regtest,
-            &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
-        );
-    }
-
-    // P2TR `tr(key)`
-    #[test]
-    fn test_p2tr_template() {
-        let prvkey =
-            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
-                .unwrap();
-        check(
-            P2TR(prvkey).build(Network::Bitcoin),
-            false,
-            true,
-            true,
-            Network::Regtest,
-            &["bcrt1pvjf9t34fznr53u5tqhejz4nr69luzkhlvsdsdfq9pglutrpve2xqnwtkqq"],
-        );
-
-        let pubkey = bitcoin::PublicKey::from_str(
-            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
-        )
-        .unwrap();
-        check(
-            P2TR(pubkey).build(Network::Bitcoin),
-            false,
-            true,
-            true,
-            Network::Regtest,
-            &["bcrt1pw74tdcrxlzn5r8z6ku2vztr86fgq0m245s72mjktf4afwzsf8ugs4evwdf"],
-        );
-    }
-
-    // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)`
-    #[test]
-    fn test_bip44_template() {
-        let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-        check(
-            Bip44(prvkey, KeychainKind::External).build(Network::Bitcoin),
-            false,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "n453VtnjDHPyDt2fDstKSu7A3YCJoHZ5g5",
-                "mvfrrumXgTtwFPWDNUecBBgzuMXhYM7KRP",
-                "mzYvhRAuQqbdSKMVVzXNYyqihgNdRadAUQ",
-            ],
-        );
-        check(
-            Bip44(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
-            false,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "muHF98X9KxEzdKrnFAX85KeHv96eXopaip",
-                "n4hpyLJE5ub6B5Bymv4eqFxS5KjrewSmYR",
-                "mgvkdv1ffmsXd2B1sRKQ5dByK3SzpG42rA",
-            ],
-        );
-    }
-
-    // BIP44 public `pkh(key/{0,1}/*)`
-    #[test]
-    fn test_bip44_public_template() {
-        let pubkey = bitcoin::bip32::Xpub::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
-        let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap();
-        check(
-            Bip44Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
-            false,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "miNG7dJTzJqNbFS19svRdTCisC65dsubtR",
-                "n2UqaDbCjWSFJvpC84m3FjUk5UaeibCzYg",
-                "muCPpS6Ue7nkzeJMWDViw7Lkwr92Yc4K8g",
-            ],
-        );
-        check(
-            Bip44Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
-            false,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "moDr3vJ8wpt5nNxSK55MPq797nXJb2Ru9H",
-                "ms7A1Yt4uTezT2XkefW12AvLoko8WfNJMG",
-                "mhYiyat2rtEnV77cFfQsW32y1m2ceCGHPo",
-            ],
-        );
-    }
-
-    // BIP49 `sh(wpkh(key/49'/0'/0'/{0,1}/*))`
-    #[test]
-    fn test_bip49_template() {
-        let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-        check(
-            Bip49(prvkey, KeychainKind::External).build(Network::Bitcoin),
-            true,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "2N9bCAJXGm168MjVwpkBdNt6ucka3PKVoUV",
-                "2NDckYkqrYyDMtttEav5hB3Bfw9EGAW5HtS",
-                "2NAFTVtksF9T4a97M7nyCjwUBD24QevZ5Z4",
-            ],
-        );
-        check(
-            Bip49(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
-            true,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "2NB3pA8PnzJLGV8YEKNDFpbViZv3Bm1K6CG",
-                "2NBiX2Wzxngb5rPiWpUiJQ2uLVB4HBjFD4p",
-                "2NA8ek4CdQ6aMkveYF6AYuEYNrftB47QGTn",
-            ],
-        );
-    }
-
-    // BIP49 public `sh(wpkh(key/{0,1}/*))`
-    #[test]
-    fn test_bip49_public_template() {
-        let pubkey = bitcoin::bip32::Xpub::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
-        let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap();
-        check(
-            Bip49Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
-            true,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt",
-                "2NCTQfJ1sZa3wQ3pPseYRHbaNEpC3AquEfX",
-                "2MveFxAuC8BYPzTybx7FxSzW8HSd8ATT4z7",
-            ],
-        );
-        check(
-            Bip49Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
-            true,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "2NF2vttKibwyxigxtx95Zw8K7JhDbo5zPVJ",
-                "2Mtmyd8taksxNVWCJ4wVvaiss7QPZGcAJuH",
-                "2NBs3CTVYPr1HCzjB4YFsnWCPCtNg8uMEfp",
-            ],
-        );
-    }
-
-    // BIP84 `wpkh(key/84'/0'/0'/{0,1}/*)`
-    #[test]
-    fn test_bip84_template() {
-        let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
-        check(
-            Bip84(prvkey, KeychainKind::External).build(Network::Bitcoin),
-            true,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s",
-                "bcrt1qx0v6zgfwe50m4kqc58cqzcyem7ay2sfl3gvqhp",
-                "bcrt1q4h7fq9zhxst6e69p3n882nfj649l7w9g3zccfp",
-            ],
-        );
-        check(
-            Bip84(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
-            true,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa",
-                "bcrt1qqqasfhxpkkf7zrxqnkr2sfhn74dgsrc3e3ky45",
-                "bcrt1qpks7n0gq74hsgsz3phn5vuazjjq0f5eqhsgyce",
-            ],
-        );
-    }
-
-    // BIP84 public `wpkh(key/{0,1}/*)`
-    #[test]
-    fn test_bip84_public_template() {
-        let pubkey = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
-        let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap();
-        check(
-            Bip84Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
-            true,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "bcrt1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2prcdvd0h",
-                "bcrt1q3lncdlwq3lgcaaeyruynjnlccr0ve0kakh6ana",
-                "bcrt1qt9800y6xl3922jy3uyl0z33jh5wfpycyhcylr9",
-            ],
-        );
-        check(
-            Bip84Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
-            true,
-            false,
-            false,
-            Network::Regtest,
-            &[
-                "bcrt1qm6wqukenh7guu792lj2njgw9n78cmwsy8xy3z2",
-                "bcrt1q694twxtjn4nnrvnyvra769j0a23rllj5c6cgwp",
-                "bcrt1qhlac3c5ranv5w5emlnqs7wxhkxt8maelylcarp",
-            ],
-        );
-    }
-
-    // BIP86 `tr(key/86'/0'/0'/{0,1}/*)`
-    // Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
-    #[test]
-    fn test_bip86_template() {
-        let prvkey = bitcoin::bip32::Xpriv::from_str("xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu").unwrap();
-        check(
-            Bip86(prvkey, KeychainKind::External).build(Network::Bitcoin),
-            false,
-            true,
-            false,
-            Network::Bitcoin,
-            &[
-                "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
-                "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
-                "bc1p0d0rhyynq0awa9m8cqrcr8f5nxqx3aw29w4ru5u9my3h0sfygnzs9khxz8",
-            ],
-        );
-        check(
-            Bip86(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
-            false,
-            true,
-            false,
-            Network::Bitcoin,
-            &[
-                "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7",
-                "bc1ptdg60grjk9t3qqcqczp4tlyy3z47yrx9nhlrjsmw36q5a72lhdrs9f00nj",
-                "bc1pgcwgsu8naxp7xlp5p7ufzs7emtfza2las7r2e7krzjhe5qj5xz2q88kmk5",
-            ],
-        );
-    }
-
-    // BIP86 public `tr(key/{0,1}/*)`
-    // Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
-    #[test]
-    fn test_bip86_public_template() {
-        let pubkey = bitcoin::bip32::Xpub::from_str("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ").unwrap();
-        let fingerprint = bitcoin::bip32::Fingerprint::from_str("73c5da0a").unwrap();
-        check(
-            Bip86Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
-            false,
-            true,
-            false,
-            Network::Bitcoin,
-            &[
-                "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
-                "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
-                "bc1p0d0rhyynq0awa9m8cqrcr8f5nxqx3aw29w4ru5u9my3h0sfygnzs9khxz8",
-            ],
-        );
-        check(
-            Bip86Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
-            false,
-            true,
-            false,
-            Network::Bitcoin,
-            &[
-                "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7",
-                "bc1ptdg60grjk9t3qqcqczp4tlyy3z47yrx9nhlrjsmw36q5a72lhdrs9f00nj",
-                "bc1pgcwgsu8naxp7xlp5p7ufzs7emtfza2las7r2e7krzjhe5qj5xz2q88kmk5",
-            ],
-        );
-    }
-}
-
-
\ 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 deleted file mode 100644 index 5112bf2794..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html +++ /dev/null @@ -1,2015 +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
-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
-
// 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.
-
-//! Key formats
-
-use crate::collections::HashSet;
-use alloc::string::{String, ToString};
-use alloc::vec::Vec;
-use core::any::TypeId;
-use core::fmt;
-use core::marker::PhantomData;
-use core::ops::Deref;
-use core::str::FromStr;
-
-use bitcoin::secp256k1::{self, Secp256k1, Signing};
-
-use bitcoin::bip32;
-use bitcoin::{key::XOnlyPublicKey, Network, PrivateKey, PublicKey};
-
-use miniscript::descriptor::{Descriptor, DescriptorXKey, Wildcard};
-pub use miniscript::descriptor::{
-    DescriptorPublicKey, DescriptorSecretKey, KeyMap, SinglePriv, SinglePub, SinglePubKey,
-    SortedMultiVec,
-};
-pub use miniscript::ScriptContext;
-use miniscript::{Miniscript, Terminal};
-
-use crate::descriptor::{CheckMiniscript, DescriptorError};
-use crate::wallet::utils::SecpCtx;
-
-#[cfg(feature = "keys-bip39")]
-#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
-pub mod bip39;
-
-/// Set of valid networks for a key
-pub type ValidNetworks = HashSet<Network>;
-
-/// Create a set containing mainnet, testnet, signet, and regtest
-pub fn any_network() -> ValidNetworks {
-    vec![
-        Network::Bitcoin,
-        Network::Testnet,
-        Network::Regtest,
-        Network::Signet,
-    ]
-    .into_iter()
-    .collect()
-}
-/// Create a set only containing mainnet
-pub fn mainnet_network() -> ValidNetworks {
-    vec![Network::Bitcoin].into_iter().collect()
-}
-/// Create a set containing testnet and regtest
-pub fn test_networks() -> ValidNetworks {
-    vec![Network::Testnet, Network::Regtest, Network::Signet]
-        .into_iter()
-        .collect()
-}
-/// Compute the intersection of two sets
-pub fn merge_networks(a: &ValidNetworks, b: &ValidNetworks) -> ValidNetworks {
-    a.intersection(b).cloned().collect()
-}
-
-/// Container for public or secret keys
-#[derive(Debug)]
-pub enum DescriptorKey<Ctx: ScriptContext> {
-    #[doc(hidden)]
-    Public(DescriptorPublicKey, ValidNetworks, PhantomData<Ctx>),
-    #[doc(hidden)]
-    Secret(DescriptorSecretKey, ValidNetworks, PhantomData<Ctx>),
-}
-
-impl<Ctx: ScriptContext> DescriptorKey<Ctx> {
-    /// Create an instance given a public key and a set of valid networks
-    pub fn from_public(public: DescriptorPublicKey, networks: ValidNetworks) -> Self {
-        DescriptorKey::Public(public, networks, PhantomData)
-    }
-
-    /// Create an instance given a secret key and a set of valid networks
-    pub fn from_secret(secret: DescriptorSecretKey, networks: ValidNetworks) -> Self {
-        DescriptorKey::Secret(secret, networks, PhantomData)
-    }
-
-    /// Override the computed set of valid networks
-    pub fn override_valid_networks(self, networks: ValidNetworks) -> Self {
-        match self {
-            DescriptorKey::Public(key, _, _) => DescriptorKey::Public(key, networks, PhantomData),
-            DescriptorKey::Secret(key, _, _) => DescriptorKey::Secret(key, networks, PhantomData),
-        }
-    }
-
-    // This method is used internally by `bdk::fragment!` and `bdk::descriptor!`. It has to be
-    // public because it is effectively called by external crates once the macros are expanded,
-    // but since it is not meant to be part of the public api we hide it from the docs.
-    #[doc(hidden)]
-    pub fn extract(
-        self,
-        secp: &SecpCtx,
-    ) -> Result<(DescriptorPublicKey, KeyMap, ValidNetworks), KeyError> {
-        match self {
-            DescriptorKey::Public(public, valid_networks, _) => {
-                Ok((public, KeyMap::default(), valid_networks))
-            }
-            DescriptorKey::Secret(secret, valid_networks, _) => {
-                let mut key_map = KeyMap::new();
-
-                let public = secret
-                    .to_public(secp)
-                    .map_err(|e| miniscript::Error::Unexpected(e.to_string()))?;
-                key_map.insert(public.clone(), secret);
-
-                Ok((public, key_map, valid_networks))
-            }
-        }
-    }
-}
-
-/// Enum representation of the known valid [`ScriptContext`]s
-#[derive(Debug, Eq, PartialEq, Copy, Clone)]
-pub enum ScriptContextEnum {
-    /// Legacy scripts
-    Legacy,
-    /// Segwitv0 scripts
-    Segwitv0,
-    /// Taproot scripts
-    Tap,
-}
-
-impl ScriptContextEnum {
-    /// Returns whether the script context is [`ScriptContextEnum::Legacy`]
-    pub fn is_legacy(&self) -> bool {
-        self == &ScriptContextEnum::Legacy
-    }
-
-    /// Returns whether the script context is [`ScriptContextEnum::Segwitv0`]
-    pub fn is_segwit_v0(&self) -> bool {
-        self == &ScriptContextEnum::Segwitv0
-    }
-
-    /// Returns whether the script context is [`ScriptContextEnum::Tap`]
-    pub fn is_taproot(&self) -> bool {
-        self == &ScriptContextEnum::Tap
-    }
-}
-
-/// Trait that adds extra useful methods to [`ScriptContext`]s
-pub trait ExtScriptContext: ScriptContext {
-    /// Returns the [`ScriptContext`] as a [`ScriptContextEnum`]
-    fn as_enum() -> ScriptContextEnum;
-
-    /// Returns whether the script context is [`Legacy`](miniscript::Legacy)
-    fn is_legacy() -> bool {
-        Self::as_enum().is_legacy()
-    }
-
-    /// Returns whether the script context is [`Segwitv0`](miniscript::Segwitv0)
-    fn is_segwit_v0() -> bool {
-        Self::as_enum().is_segwit_v0()
-    }
-
-    /// Returns whether the script context is [`Tap`](miniscript::Tap), aka Taproot or Segwit V1
-    fn is_taproot() -> bool {
-        Self::as_enum().is_taproot()
-    }
-}
-
-impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
-    fn as_enum() -> ScriptContextEnum {
-        match TypeId::of::<Ctx>() {
-            t if t == TypeId::of::<miniscript::Legacy>() => ScriptContextEnum::Legacy,
-            t if t == TypeId::of::<miniscript::Segwitv0>() => ScriptContextEnum::Segwitv0,
-            t if t == TypeId::of::<miniscript::Tap>() => ScriptContextEnum::Tap,
-            _ => unimplemented!("Unknown ScriptContext type"),
-        }
-    }
-}
-
-/// 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
-/// formats, like the mnemonics used by Electrum wallets, encode internally whether the wallet is
-/// legacy or segwit. Thus, trying to turn a valid legacy mnemonic into a `DescriptorKey`
-/// that would become part of a segwit descriptor should fail.
-///
-/// For key types that do care about this, the [`ExtScriptContext`] trait provides some useful
-/// methods that can be used to check at runtime which `Ctx` is being used.
-///
-/// For key types that can do this check statically (because they can only work within a
-/// single `Ctx`), the "specialized" trait can be implemented to make the compiler handle the type
-/// checking.
-///
-/// Keys also have control over the networks they support: constructing the return object with
-/// [`DescriptorKey::from_public`] or [`DescriptorKey::from_secret`] allows to specify a set of
-/// [`ValidNetworks`].
-///
-/// ## Examples
-///
-/// Key type valid in any context:
-///
-/// ```
-/// use bdk::bitcoin::PublicKey;
-///
-/// use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError, ScriptContext};
-///
-/// pub struct MyKeyType {
-///     pubkey: PublicKey,
-/// }
-///
-/// impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for MyKeyType {
-///     fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-///         self.pubkey.into_descriptor_key()
-///     }
-/// }
-/// ```
-///
-/// Key type that is only valid on mainnet:
-///
-/// ```
-/// use bdk::bitcoin::PublicKey;
-///
-/// use bdk::keys::{
-///     mainnet_network, DescriptorKey, DescriptorPublicKey, IntoDescriptorKey, KeyError,
-///     ScriptContext, SinglePub, SinglePubKey,
-/// };
-///
-/// pub struct MyKeyType {
-///     pubkey: PublicKey,
-/// }
-///
-/// impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for MyKeyType {
-///     fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-///         Ok(DescriptorKey::from_public(
-///             DescriptorPublicKey::Single(SinglePub {
-///                 origin: None,
-///                 key: SinglePubKey::FullKey(self.pubkey),
-///             }),
-///             mainnet_network(),
-///         ))
-///     }
-/// }
-/// ```
-///
-/// Key type that internally encodes in which context it's valid. The context is checked at runtime:
-///
-/// ```
-/// use bdk::bitcoin::PublicKey;
-///
-/// use bdk::keys::{DescriptorKey, ExtScriptContext, IntoDescriptorKey, KeyError, ScriptContext};
-///
-/// pub struct MyKeyType {
-///     is_legacy: bool,
-///     pubkey: PublicKey,
-/// }
-///
-/// impl<Ctx: ScriptContext + 'static> IntoDescriptorKey<Ctx> for MyKeyType {
-///     fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-///         if Ctx::is_legacy() == self.is_legacy {
-///             self.pubkey.into_descriptor_key()
-///         } else {
-///             Err(KeyError::InvalidScriptContext)
-///         }
-///     }
-/// }
-/// ```
-///
-/// Key type that can only work within [`miniscript::Segwitv0`] context. Only the specialized version
-/// of the trait is implemented.
-///
-/// This example deliberately fails to compile, to demonstrate how the compiler can catch when keys
-/// are misused. In this case, the "segwit-only" key is used to build a `pkh()` descriptor, which
-/// makes the compiler (correctly) fail.
-///
-/// ```compile_fail
-/// use bdk::bitcoin::PublicKey;
-/// use core::str::FromStr;
-///
-/// use bdk::keys::{DescriptorKey, IntoDescriptorKey, KeyError};
-///
-/// pub struct MySegwitOnlyKeyType {
-///     pubkey: PublicKey,
-/// }
-///
-/// impl IntoDescriptorKey<bdk::miniscript::Segwitv0> for MySegwitOnlyKeyType {
-///     fn into_descriptor_key(self) -> Result<DescriptorKey<bdk::miniscript::Segwitv0>, KeyError> {
-///         self.pubkey.into_descriptor_key()
-///     }
-/// }
-///
-/// let key = MySegwitOnlyKeyType {
-///     pubkey: PublicKey::from_str("...")?,
-/// };
-/// let (descriptor, _, _) = bdk::descriptor!(pkh(key))?;
-/// //                                       ^^^^^ changing this to `wpkh` would make it compile
-///
-/// # Ok::<_, Box<dyn std::error::Error>>(())
-/// ```
-pub trait IntoDescriptorKey<Ctx: ScriptContext>: Sized {
-    /// Turn the key into a [`DescriptorKey`] within the requested [`ScriptContext`]
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError>;
-}
-
-/// Enum for extended keys that can be either `xprv` or `xpub`
-///
-/// An instance of [`ExtendedKey`] can be constructed from an [`Xpriv`](bip32::Xpriv)
-/// or an [`Xpub`](bip32::Xpub) by using the `From` trait.
-///
-/// Defaults to the [`Legacy`](miniscript::Legacy) context.
-pub enum ExtendedKey<Ctx: ScriptContext = miniscript::Legacy> {
-    /// A private extended key, aka an `xprv`
-    Private((bip32::Xpriv, PhantomData<Ctx>)),
-    /// A public extended key, aka an `xpub`
-    Public((bip32::Xpub, PhantomData<Ctx>)),
-}
-
-impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
-    /// Return whether or not the key contains the private data
-    pub fn has_secret(&self) -> bool {
-        match self {
-            ExtendedKey::Private(_) => true,
-            ExtendedKey::Public(_) => false,
-        }
-    }
-
-    /// Transform the [`ExtendedKey`] into an [`Xpriv`](bip32::Xpriv) for the
-    /// given [`Network`], if the key contains the private data
-    pub fn into_xprv(self, network: Network) -> Option<bip32::Xpriv> {
-        match self {
-            ExtendedKey::Private((mut xprv, _)) => {
-                xprv.network = network;
-                Some(xprv)
-            }
-            ExtendedKey::Public(_) => None,
-        }
-    }
-
-    /// Transform the [`ExtendedKey`] into an [`Xpub`](bip32::Xpub) for the
-    /// given [`Network`]
-    pub fn into_xpub<C: Signing>(
-        self,
-        network: bitcoin::Network,
-        secp: &Secp256k1<C>,
-    ) -> bip32::Xpub {
-        let mut xpub = match self {
-            ExtendedKey::Private((xprv, _)) => bip32::Xpub::from_priv(secp, &xprv),
-            ExtendedKey::Public((xpub, _)) => xpub,
-        };
-
-        xpub.network = network;
-        xpub
-    }
-}
-
-impl<Ctx: ScriptContext> From<bip32::Xpub> for ExtendedKey<Ctx> {
-    fn from(xpub: bip32::Xpub) -> Self {
-        ExtendedKey::Public((xpub, PhantomData))
-    }
-}
-
-impl<Ctx: ScriptContext> From<bip32::Xpriv> for ExtendedKey<Ctx> {
-    fn from(xprv: bip32::Xpriv) -> Self {
-        ExtendedKey::Private((xprv, PhantomData))
-    }
-}
-
-/// Trait for keys that can be derived.
-///
-/// When extra metadata are provided, a [`DerivableKey`] can be transformed into a
-/// [`DescriptorKey`]: the trait [`IntoDescriptorKey`] is automatically implemented
-/// for `(DerivableKey, DerivationPath)` and
-/// `(DerivableKey, KeySource, DerivationPath)` tuples.
-///
-/// For key types that don't encode any indication about the path to use (like bip39), it's
-/// generally recommended to implement this trait instead of [`IntoDescriptorKey`]. The same
-/// rules regarding script context and valid networks apply.
-///
-/// ## Examples
-///
-/// Key types that can be directly converted into an [`Xpriv`] or
-/// an [`Xpub`] can implement only the required `into_extended_key()` method.
-///
-/// ```
-/// use bdk::bitcoin;
-/// use bdk::bitcoin::bip32;
-/// use bdk::keys::{DerivableKey, ExtendedKey, KeyError, ScriptContext};
-///
-/// struct MyCustomKeyType {
-///     key_data: bitcoin::PrivateKey,
-///     chain_code: [u8; 32],
-///     network: bitcoin::Network,
-/// }
-///
-/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
-///     fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
-///         let xprv = bip32::Xpriv {
-///             network: self.network,
-///             depth: 0,
-///             parent_fingerprint: bip32::Fingerprint::default(),
-///             private_key: self.key_data.inner,
-///             chain_code: bip32::ChainCode::from(&self.chain_code),
-///             child_number: bip32::ChildNumber::Normal { index: 0 },
-///         };
-///
-///         xprv.into_extended_key()
-///     }
-/// }
-/// ```
-///
-/// Types that don't internally encode the [`Network`] in which they are valid need some extra
-/// steps to override the set of valid networks, otherwise only the network specified in the
-/// [`Xpriv`] or [`Xpub`] will be considered valid.
-///
-/// ```
-/// use bdk::bitcoin;
-/// use bdk::bitcoin::bip32;
-/// use bdk::keys::{
-///     any_network, DerivableKey, DescriptorKey, ExtendedKey, KeyError, ScriptContext,
-/// };
-///
-/// struct MyCustomKeyType {
-///     key_data: bitcoin::PrivateKey,
-///     chain_code: [u8; 32],
-/// }
-///
-/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
-///     fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
-///         let xprv = bip32::Xpriv {
-///             network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
-///             depth: 0,
-///             parent_fingerprint: bip32::Fingerprint::default(),
-///             private_key: self.key_data.inner,
-///             chain_code: bip32::ChainCode::from(&self.chain_code),
-///             child_number: bip32::ChildNumber::Normal { index: 0 },
-///         };
-///
-///         xprv.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)?;
-///
-///         // Override the set of valid networks here
-///         Ok(descriptor_key.override_valid_networks(any_network()))
-///     }
-/// }
-/// ```
-///
-/// [`DerivationPath`]: (bip32::DerivationPath)
-/// [`Xpriv`]: (bip32::Xpriv)
-/// [`Xpub`]: (bip32::Xpub)
-pub trait DerivableKey<Ctx: ScriptContext = miniscript::Legacy>: Sized {
-    /// Consume `self` and turn it into an [`ExtendedKey`]
-    #[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};
-use bdk::keys::bip39::{Mnemonic, Language};
-
-# fn main() -> Result<(), Box<dyn std::error::Error>> {
-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();
-# Ok(()) }
-```
-"##
-    )]
-    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError>;
-
-    /// Consume `self` and turn it into a [`DescriptorKey`] by adding the extra metadata, such as
-    /// key origin and derivation path
-    fn into_descriptor_key(
-        self,
-        origin: Option<bip32::KeySource>,
-        derivation_path: bip32::DerivationPath,
-    ) -> Result<DescriptorKey<Ctx>, KeyError> {
-        match self.into_extended_key()? {
-            ExtendedKey::Private((xprv, _)) => DescriptorSecretKey::XPrv(DescriptorXKey {
-                origin,
-                xkey: xprv,
-                derivation_path,
-                wildcard: Wildcard::Unhardened,
-            })
-            .into_descriptor_key(),
-            ExtendedKey::Public((xpub, _)) => DescriptorPublicKey::XPub(DescriptorXKey {
-                origin,
-                xkey: xpub,
-                derivation_path,
-                wildcard: Wildcard::Unhardened,
-            })
-            .into_descriptor_key(),
-        }
-    }
-}
-
-/// Identity conversion
-impl<Ctx: ScriptContext> DerivableKey<Ctx> for ExtendedKey<Ctx> {
-    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
-        Ok(self)
-    }
-}
-
-impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::Xpub {
-    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
-        Ok(self.into())
-    }
-}
-
-impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::Xpriv {
-    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
-        Ok(self.into())
-    }
-}
-
-/// Output of a [`GeneratableKey`] key generation
-pub struct GeneratedKey<K, Ctx: ScriptContext> {
-    key: K,
-    valid_networks: ValidNetworks,
-    phantom: PhantomData<Ctx>,
-}
-
-impl<K, Ctx: ScriptContext> GeneratedKey<K, Ctx> {
-    fn new(key: K, valid_networks: ValidNetworks) -> Self {
-        GeneratedKey {
-            key,
-            valid_networks,
-            phantom: PhantomData,
-        }
-    }
-
-    /// Consumes `self` and returns the key
-    pub fn into_key(self) -> K {
-        self.key
-    }
-}
-
-impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx> {
-    type Target = K;
-
-    fn deref(&self) -> &Self::Target {
-        &self.key
-    }
-}
-
-impl<K: Clone, Ctx: ScriptContext> Clone for GeneratedKey<K, Ctx> {
-    fn clone(&self) -> GeneratedKey<K, Ctx> {
-        GeneratedKey {
-            key: self.key.clone(),
-            valid_networks: self.valid_networks.clone(),
-            phantom: self.phantom,
-        }
-    }
-}
-
-// Make generated "derivable" keys themselves "derivable". Also make sure they are assigned the
-// right `valid_networks`.
-impl<Ctx, K> DerivableKey<Ctx> for GeneratedKey<K, Ctx>
-where
-    Ctx: ScriptContext,
-    K: DerivableKey<Ctx>,
-{
-    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
-        self.key.into_extended_key()
-    }
-
-    fn into_descriptor_key(
-        self,
-        origin: Option<bip32::KeySource>,
-        derivation_path: bip32::DerivationPath,
-    ) -> Result<DescriptorKey<Ctx>, KeyError> {
-        let descriptor_key = self.key.into_descriptor_key(origin, derivation_path)?;
-        Ok(descriptor_key.override_valid_networks(self.valid_networks))
-    }
-}
-
-// Make generated keys directly usable in descriptors, and make sure they get assigned the right
-// `valid_networks`.
-impl<Ctx, K> IntoDescriptorKey<Ctx> for GeneratedKey<K, Ctx>
-where
-    Ctx: ScriptContext,
-    K: IntoDescriptorKey<Ctx>,
-{
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        let desc_key = self.key.into_descriptor_key()?;
-        Ok(desc_key.override_valid_networks(self.valid_networks))
-    }
-}
-
-/// Trait for keys that can be generated
-///
-/// The same rules about [`ScriptContext`] and [`ValidNetworks`] from [`IntoDescriptorKey`] apply.
-///
-/// This trait is particularly useful when combined with [`DerivableKey`]: if `Self`
-/// 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`].
-pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
-    /// Type specifying the amount of entropy required e.g. `[u8;32]`
-    type Entropy: AsMut<[u8]> + Default;
-
-    /// Extra options required by the `generate_with_entropy`
-    type Options;
-    /// Returned error in case of failure
-    type Error: core::fmt::Debug;
-
-    /// Generate a key given the extra options and the entropy
-    fn generate_with_entropy(
-        options: Self::Options,
-        entropy: Self::Entropy,
-    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>;
-
-    /// Generate a key given the options with a random entropy
-    fn generate(options: Self::Options) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
-        use rand::{thread_rng, Rng};
-
-        let mut entropy = Self::Entropy::default();
-        thread_rng().fill(entropy.as_mut());
-        Self::generate_with_entropy(options, entropy)
-    }
-}
-
-/// Trait that allows generating a key with the default options
-///
-/// This trait is automatically implemented if the [`GeneratableKey::Options`] implements [`Default`].
-pub trait GeneratableDefaultOptions<Ctx>: GeneratableKey<Ctx>
-where
-    Ctx: ScriptContext,
-    <Self as GeneratableKey<Ctx>>::Options: Default,
-{
-    /// Generate a key with the default options and a given entropy
-    fn generate_with_entropy_default(
-        entropy: Self::Entropy,
-    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
-        Self::generate_with_entropy(Default::default(), entropy)
-    }
-
-    /// Generate a key with the default options and a random entropy
-    fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
-        Self::generate(Default::default())
-    }
-}
-
-/// Automatic implementation of [`GeneratableDefaultOptions`] for [`GeneratableKey`]s where
-/// `Options` implements `Default`
-impl<Ctx, K> GeneratableDefaultOptions<Ctx> for K
-where
-    Ctx: ScriptContext,
-    K: GeneratableKey<Ctx>,
-    <K as GeneratableKey<Ctx>>::Options: Default,
-{
-}
-
-impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::Xpriv {
-    type Entropy = [u8; 32];
-
-    type Options = ();
-    type Error = bip32::Error;
-
-    fn generate_with_entropy(
-        _: Self::Options,
-        entropy: Self::Entropy,
-    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
-        // pick a arbitrary network here, but say that we support all of them
-        let xprv = bip32::Xpriv::new_master(Network::Bitcoin, entropy.as_ref())?;
-        Ok(GeneratedKey::new(xprv, any_network()))
-    }
-}
-
-/// Options for generating a [`PrivateKey`]
-///
-/// Defaults to creating compressed keys, which save on-chain bytes and fees
-#[derive(Debug, Copy, Clone)]
-pub struct PrivateKeyGenerateOptions {
-    /// Whether the generated key should be "compressed" or not
-    pub compressed: bool,
-}
-
-impl Default for PrivateKeyGenerateOptions {
-    fn default() -> Self {
-        PrivateKeyGenerateOptions { compressed: true }
-    }
-}
-
-impl<Ctx: ScriptContext> GeneratableKey<Ctx> for PrivateKey {
-    type Entropy = [u8; secp256k1::constants::SECRET_KEY_SIZE];
-
-    type Options = PrivateKeyGenerateOptions;
-    type Error = bip32::Error;
-
-    fn generate_with_entropy(
-        options: Self::Options,
-        entropy: Self::Entropy,
-    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
-        // pick a arbitrary network here, but say that we support all of them
-        let inner = secp256k1::SecretKey::from_slice(&entropy)?;
-        let private_key = PrivateKey {
-            compressed: options.compressed,
-            network: Network::Bitcoin,
-            inner,
-        };
-
-        Ok(GeneratedKey::new(private_key, any_network()))
-    }
-}
-
-impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> IntoDescriptorKey<Ctx>
-    for (T, bip32::DerivationPath)
-{
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        self.0.into_descriptor_key(None, self.1)
-    }
-}
-
-impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> IntoDescriptorKey<Ctx>
-    for (T, bip32::KeySource, bip32::DerivationPath)
-{
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        self.0.into_descriptor_key(Some(self.1), self.2)
-    }
-}
-
-fn expand_multi_keys<Pk: IntoDescriptorKey<Ctx>, Ctx: ScriptContext>(
-    pks: Vec<Pk>,
-    secp: &SecpCtx,
-) -> Result<(Vec<DescriptorPublicKey>, KeyMap, ValidNetworks), KeyError> {
-    let (pks, key_maps_networks): (Vec<_>, Vec<_>) = pks
-        .into_iter()
-        .map(|key| key.into_descriptor_key()?.extract(secp))
-        .collect::<Result<Vec<_>, _>>()?
-        .into_iter()
-        .map(|(a, b, c)| (a, (b, c)))
-        .unzip();
-
-    let (key_map, valid_networks) = key_maps_networks.into_iter().fold(
-        (KeyMap::default(), any_network()),
-        |(mut keys_acc, net_acc), (key, net)| {
-            keys_acc.extend(key);
-            let net_acc = merge_networks(&net_acc, &net);
-
-            (keys_acc, net_acc)
-        },
-    );
-
-    Ok((pks, key_map, valid_networks))
-}
-
-// Used internally by `bdk::fragment!` to build `pk_k()` fragments
-#[doc(hidden)]
-pub fn make_pk<Pk: IntoDescriptorKey<Ctx>, Ctx: ScriptContext>(
-    descriptor_key: Pk,
-    secp: &SecpCtx,
-) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), DescriptorError> {
-    let (key, key_map, valid_networks) = descriptor_key.into_descriptor_key()?.extract(secp)?;
-    let minisc = Miniscript::from_ast(Terminal::PkK(key))?;
-
-    minisc.check_miniscript()?;
-
-    Ok((minisc, key_map, valid_networks))
-}
-
-// Used internally by `bdk::fragment!` to build `pk_h()` fragments
-#[doc(hidden)]
-pub fn make_pkh<Pk: IntoDescriptorKey<Ctx>, Ctx: ScriptContext>(
-    descriptor_key: Pk,
-    secp: &SecpCtx,
-) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), DescriptorError> {
-    let (key, key_map, valid_networks) = descriptor_key.into_descriptor_key()?.extract(secp)?;
-    let minisc = Miniscript::from_ast(Terminal::PkH(key))?;
-
-    minisc.check_miniscript()?;
-
-    Ok((minisc, key_map, valid_networks))
-}
-
-// Used internally by `bdk::fragment!` to build `multi()` fragments
-#[doc(hidden)]
-pub fn make_multi<
-    Pk: IntoDescriptorKey<Ctx>,
-    Ctx: ScriptContext,
-    V: Fn(usize, Vec<DescriptorPublicKey>) -> Terminal<DescriptorPublicKey, Ctx>,
->(
-    thresh: usize,
-    variant: V,
-    pks: Vec<Pk>,
-    secp: &SecpCtx,
-) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), DescriptorError> {
-    let (pks, key_map, valid_networks) = expand_multi_keys(pks, secp)?;
-    let minisc = Miniscript::from_ast(variant(thresh, pks))?;
-
-    minisc.check_miniscript()?;
-
-    Ok((minisc, key_map, valid_networks))
-}
-
-// Used internally by `bdk::descriptor!` to build `sortedmulti()` fragments
-#[doc(hidden)]
-pub fn make_sortedmulti<Pk, Ctx, F>(
-    thresh: usize,
-    pks: Vec<Pk>,
-    build_desc: F,
-    secp: &SecpCtx,
-) -> Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>
-where
-    Pk: IntoDescriptorKey<Ctx>,
-    Ctx: ScriptContext,
-    F: Fn(
-        usize,
-        Vec<DescriptorPublicKey>,
-    ) -> Result<(Descriptor<DescriptorPublicKey>, PhantomData<Ctx>), DescriptorError>,
-{
-    let (pks, key_map, valid_networks) = expand_multi_keys(pks, secp)?;
-    let descriptor = build_desc(thresh, pks)?.0;
-
-    Ok((descriptor, key_map, valid_networks))
-}
-
-/// The "identity" conversion is used internally by some `bdk::fragment`s
-impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for DescriptorKey<Ctx> {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        Ok(self)
-    }
-}
-
-impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for DescriptorPublicKey {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        let networks = match self {
-            DescriptorPublicKey::Single(_) => any_network(),
-            DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. })
-                if xkey.network == Network::Bitcoin =>
-            {
-                mainnet_network()
-            }
-            _ => test_networks(),
-        };
-
-        Ok(DescriptorKey::from_public(self, networks))
-    }
-}
-
-impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for PublicKey {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        DescriptorPublicKey::Single(SinglePub {
-            key: SinglePubKey::FullKey(self),
-            origin: None,
-        })
-        .into_descriptor_key()
-    }
-}
-
-impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for XOnlyPublicKey {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        DescriptorPublicKey::Single(SinglePub {
-            key: SinglePubKey::XOnly(self),
-            origin: None,
-        })
-        .into_descriptor_key()
-    }
-}
-
-impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for DescriptorSecretKey {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        let networks = match &self {
-            DescriptorSecretKey::Single(sk) if sk.key.network == Network::Bitcoin => {
-                mainnet_network()
-            }
-            DescriptorSecretKey::XPrv(DescriptorXKey { xkey, .. })
-                if xkey.network == Network::Bitcoin =>
-            {
-                mainnet_network()
-            }
-            _ => test_networks(),
-        };
-
-        Ok(DescriptorKey::from_secret(self, networks))
-    }
-}
-
-impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for &'_ str {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        DescriptorSecretKey::from_str(self)
-            .map_err(|e| KeyError::Message(e.to_string()))?
-            .into_descriptor_key()
-    }
-}
-
-impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for PrivateKey {
-    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
-        DescriptorSecretKey::Single(SinglePriv {
-            key: self,
-            origin: None,
-        })
-        .into_descriptor_key()
-    }
-}
-
-/// Errors thrown while working with [`keys`](crate::keys)
-#[derive(Debug)]
-pub enum KeyError {
-    /// The key cannot exist in the given script context
-    InvalidScriptContext,
-    /// The key is not valid for the given network
-    InvalidNetwork,
-    /// The key has an invalid checksum
-    InvalidChecksum,
-
-    /// Custom error message
-    Message(String),
-
-    /// BIP32 error
-    Bip32(bitcoin::bip32::Error),
-    /// Miniscript error
-    Miniscript(miniscript::Error),
-}
-
-impl From<miniscript::Error> for KeyError {
-    fn from(err: miniscript::Error) -> Self {
-        KeyError::Miniscript(err)
-    }
-}
-
-impl From<bip32::Error> for KeyError {
-    fn from(err: bip32::Error) -> Self {
-        KeyError::Bip32(err)
-    }
-}
-
-impl fmt::Display for KeyError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::InvalidScriptContext => write!(f, "Invalid script context"),
-            Self::InvalidNetwork => write!(f, "Invalid network"),
-            Self::InvalidChecksum => write!(f, "Invalid checksum"),
-            Self::Message(err) => write!(f, "{}", err),
-            Self::Bip32(err) => write!(f, "BIP32 error: {}", err),
-            Self::Miniscript(err) => write!(f, "Miniscript error: {}", err),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for KeyError {}
-
-#[cfg(test)]
-pub mod test {
-    use bitcoin::bip32;
-
-    use super::*;
-
-    pub const TEST_ENTROPY: [u8; 32] = [0xAA; 32];
-
-    #[test]
-    fn test_keys_generate_xprv() {
-        let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> =
-            bip32::Xpriv::generate_with_entropy_default(TEST_ENTROPY).unwrap();
-
-        assert_eq!(generated_xprv.valid_networks, any_network());
-        assert_eq!(generated_xprv.to_string(), "xprv9s21ZrQH143K4Xr1cJyqTvuL2FWR8eicgY9boWqMBv8MDVUZ65AXHnzBrK1nyomu6wdcabRgmGTaAKawvhAno1V5FowGpTLVx3jxzE5uk3Q");
-    }
-
-    #[test]
-    fn test_keys_generate_wif() {
-        let generated_wif: GeneratedKey<_, miniscript::Segwitv0> =
-            bitcoin::PrivateKey::generate_with_entropy_default(TEST_ENTROPY).unwrap();
-
-        assert_eq!(generated_wif.valid_networks, any_network());
-        assert_eq!(
-            generated_wif.to_string(),
-            "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch"
-        );
-    }
-
-    #[cfg(feature = "keys-bip39")]
-    #[test]
-    fn test_keys_wif_network_bip39() {
-        let xkey: ExtendedKey = bip39::Mnemonic::parse_in(
-            bip39::Language::English,
-            "jelly crash boy whisper mouse ecology tuna soccer memory million news short",
-        )
-        .unwrap()
-        .into_extended_key()
-        .unwrap();
-        let xprv = xkey.into_xprv(Network::Testnet).unwrap();
-
-        assert_eq!(xprv.network, Network::Testnet);
-    }
-}
-
-
\ No newline at end of file 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 deleted file mode 100644 index 6a16ac8dad..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/lib.rs.html +++ /dev/null @@ -1,97 +0,0 @@ -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
-
#![doc = include_str!("../README.md")]
-// 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")
-)]
-#![no_std]
-#![warn(missing_docs)]
-
-#[cfg(feature = "std")]
-#[macro_use]
-extern crate std;
-
-#[doc(hidden)]
-#[macro_use]
-pub extern crate alloc;
-
-pub extern crate bitcoin;
-pub extern crate miniscript;
-extern crate serde;
-extern crate serde_json;
-
-#[cfg(feature = "keys-bip39")]
-extern crate bip39;
-
-pub mod descriptor;
-pub mod keys;
-pub mod psbt;
-pub(crate) mod types;
-pub mod wallet;
-
-pub use descriptor::template;
-pub use descriptor::HdKeyPaths;
-pub use types::*;
-pub use wallet::signer;
-pub use wallet::signer::SignOptions;
-pub use wallet::tx_builder::TxBuilder;
-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 deleted file mode 100644 index b81eba9afb..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/psbt/mod.rs.html +++ /dev/null @@ -1,153 +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
-
// 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.
-
-//! Additional functions on the `rust-bitcoin` `Psbt` structure.
-
-use alloc::vec::Vec;
-use bitcoin::Amount;
-use bitcoin::FeeRate;
-use bitcoin::Psbt;
-use bitcoin::TxOut;
-
-// TODO upstream the functions here to `rust-bitcoin`?
-
-/// Trait to add functions to extract utxos and calculate fees.
-pub trait PsbtUtils {
-    /// Get the `TxOut` for the specified input index, if it doesn't exist in the PSBT `None` is returned.
-    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
-
-    /// 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.
-    fn fee_amount(&self) -> Option<u64>;
-
-    /// The transaction's fee rate. This value will only be accurate if calculated AFTER the
-    /// `Psbt` is finalized and all witness/signature data is added to the
-    /// transaction.
-    /// If the PSBT is missing a TxOut for an input returns None.
-    fn fee_rate(&self) -> Option<FeeRate>;
-}
-
-impl PsbtUtils for Psbt {
-    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
-        let tx = &self.unsigned_tx;
-        let input = self.inputs.get(input_index)?;
-
-        match (&input.witness_utxo, &input.non_witness_utxo) {
-            (Some(_), _) => input.witness_utxo.clone(),
-            (_, Some(_)) => input.non_witness_utxo.as_ref().map(|in_tx| {
-                in_tx.output[tx.input[input_index].previous_output.vout as usize].clone()
-            }),
-            _ => None,
-        }
-    }
-
-    fn fee_amount(&self) -> Option<u64> {
-        let tx = &self.unsigned_tx;
-        let utxos: Option<Vec<TxOut>> = (0..tx.input.len()).map(|i| self.get_utxo_for(i)).collect();
-
-        utxos.map(|inputs| {
-            let input_amount: u64 = inputs.iter().map(|i| i.value.to_sat()).sum();
-            let output_amount: u64 = self
-                .unsigned_tx
-                .output
-                .iter()
-                .map(|o| o.value.to_sat())
-                .sum();
-            input_amount
-                .checked_sub(output_amount)
-                .expect("input amount must be greater than output amount")
-        })
-    }
-
-    fn fee_rate(&self) -> Option<FeeRate> {
-        let fee_amount = self.fee_amount();
-        let weight = self.clone().extract_tx().ok()?.weight();
-        fee_amount.map(|fee| Amount::from_sat(fee) / weight)
-    }
-}
-
-
\ 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 deleted file mode 100644 index 4c237682e7..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html +++ /dev/null @@ -1,273 +0,0 @@ -types.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
-
// 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 alloc::boxed::Box;
-use core::convert::AsRef;
-
-use bdk_chain::ConfirmationTime;
-use bitcoin::blockdata::transaction::{OutPoint, Sequence, TxOut};
-use bitcoin::psbt;
-
-use serde::{Deserialize, Serialize};
-
-/// Types of keychains
-#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
-pub enum KeychainKind {
-    /// External keychain, used for deriving recipient addresses.
-    External = 0,
-    /// Internal keychain, used for deriving change addresses.
-    Internal = 1,
-}
-
-impl KeychainKind {
-    /// Return [`KeychainKind`] as a byte
-    pub fn as_byte(&self) -> u8 {
-        match self {
-            KeychainKind::External => b'e',
-            KeychainKind::Internal => b'i',
-        }
-    }
-}
-
-impl AsRef<[u8]> for KeychainKind {
-    fn as_ref(&self) -> &[u8] {
-        match self {
-            KeychainKind::External => b"e",
-            KeychainKind::Internal => b"i",
-        }
-    }
-}
-
-/// An unspent output owned by a [`Wallet`].
-///
-/// [`Wallet`]: crate::Wallet
-#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
-pub struct LocalOutput {
-    /// Reference to a transaction output
-    pub outpoint: OutPoint,
-    /// Transaction output
-    pub txout: TxOut,
-    /// Type of keychain
-    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`.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct WeightedUtxo {
-    /// 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.
-    ///
-    /// [weight units]: https://en.bitcoin.it/wiki/Weight_units
-    pub satisfaction_weight: usize,
-    /// The UTXO
-    pub utxo: Utxo,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-/// An unspent transaction output (UTXO).
-pub enum Utxo {
-    /// A UTXO owned by the local wallet.
-    Local(LocalOutput),
-    /// A UTXO owned by another wallet.
-    Foreign {
-        /// The location of the output.
-        outpoint: OutPoint,
-        /// The nSequence value to set for this input.
-        sequence: Option<Sequence>,
-        /// The information about the input we require to add it to a PSBT.
-        // Box it to stop the type being too big.
-        psbt_input: Box<psbt::Input>,
-    },
-}
-
-impl Utxo {
-    /// Get the location of the UTXO
-    pub fn outpoint(&self) -> OutPoint {
-        match &self {
-            Utxo::Local(local) => local.outpoint,
-            Utxo::Foreign { outpoint, .. } => *outpoint,
-        }
-    }
-
-    /// Get the `TxOut` of the UTXO
-    pub fn txout(&self) -> &TxOut {
-        match &self {
-            Utxo::Local(local) => &local.txout,
-            Utxo::Foreign {
-                outpoint,
-                psbt_input,
-                ..
-            } => {
-                if let Some(prev_tx) = &psbt_input.non_witness_utxo {
-                    return &prev_tx.output[outpoint.vout as usize];
-                }
-
-                if let Some(txout) = &psbt_input.witness_utxo {
-                    return txout;
-                }
-
-                unreachable!("Foreign UTXOs will always have one of these set")
-            }
-        }
-    }
-
-    /// Get the sequence number if an explicit sequence number has to be set for this input.
-    pub fn sequence(&self) -> Option<Sequence> {
-        match self {
-            Utxo::Local(_) => None,
-            Utxo::Foreign { sequence, .. } => *sequence,
-        }
-    }
-}
-
-
\ No newline at end of file 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 deleted file mode 100644 index b9ef904727..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html +++ /dev/null @@ -1,3207 +0,0 @@ -coin_selection.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
-1148
-1149
-1150
-1151
-1152
-1153
-1154
-1155
-1156
-1157
-1158
-1159
-1160
-1161
-1162
-1163
-1164
-1165
-1166
-1167
-1168
-1169
-1170
-1171
-1172
-1173
-1174
-1175
-1176
-1177
-1178
-1179
-1180
-1181
-1182
-1183
-1184
-1185
-1186
-1187
-1188
-1189
-1190
-1191
-1192
-1193
-1194
-1195
-1196
-1197
-1198
-1199
-1200
-1201
-1202
-1203
-1204
-1205
-1206
-1207
-1208
-1209
-1210
-1211
-1212
-1213
-1214
-1215
-1216
-1217
-1218
-1219
-1220
-1221
-1222
-1223
-1224
-1225
-1226
-1227
-1228
-1229
-1230
-1231
-1232
-1233
-1234
-1235
-1236
-1237
-1238
-1239
-1240
-1241
-1242
-1243
-1244
-1245
-1246
-1247
-1248
-1249
-1250
-1251
-1252
-1253
-1254
-1255
-1256
-1257
-1258
-1259
-1260
-1261
-1262
-1263
-1264
-1265
-1266
-1267
-1268
-1269
-1270
-1271
-1272
-1273
-1274
-1275
-1276
-1277
-1278
-1279
-1280
-1281
-1282
-1283
-1284
-1285
-1286
-1287
-1288
-1289
-1290
-1291
-1292
-1293
-1294
-1295
-1296
-1297
-1298
-1299
-1300
-1301
-1302
-1303
-1304
-1305
-1306
-1307
-1308
-1309
-1310
-1311
-1312
-1313
-1314
-1315
-1316
-1317
-1318
-1319
-1320
-1321
-1322
-1323
-1324
-1325
-1326
-1327
-1328
-1329
-1330
-1331
-1332
-1333
-1334
-1335
-1336
-1337
-1338
-1339
-1340
-1341
-1342
-1343
-1344
-1345
-1346
-1347
-1348
-1349
-1350
-1351
-1352
-1353
-1354
-1355
-1356
-1357
-1358
-1359
-1360
-1361
-1362
-1363
-1364
-1365
-1366
-1367
-1368
-1369
-1370
-1371
-1372
-1373
-1374
-1375
-1376
-1377
-1378
-1379
-1380
-1381
-1382
-1383
-1384
-1385
-1386
-1387
-1388
-1389
-1390
-1391
-1392
-1393
-1394
-1395
-1396
-1397
-1398
-1399
-1400
-1401
-1402
-1403
-1404
-1405
-1406
-1407
-1408
-1409
-1410
-1411
-1412
-1413
-1414
-1415
-1416
-1417
-1418
-1419
-1420
-1421
-1422
-1423
-1424
-1425
-1426
-1427
-1428
-1429
-1430
-1431
-1432
-1433
-1434
-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
-1596
-1597
-1598
-1599
-1600
-1601
-1602
-
// 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.
-
-//! Coin selection
-//!
-//! This module provides the trait [`CoinSelectionAlgorithm`] that can be implemented to
-//! define custom coin selection algorithms.
-//!
-//! You can specify a custom coin selection algorithm through the [`coin_selection`] method on
-//! [`TxBuilder`]. [`DefaultCoinSelectionAlgorithm`] aliases the coin selection algorithm that will
-//! be used if it is not explicitly set.
-//!
-//! [`TxBuilder`]: super::tx_builder::TxBuilder
-//! [`coin_selection`]: super::tx_builder::TxBuilder::coin_selection
-//!
-//! ## Example
-//!
-//! ```
-//! # use std::str::FromStr;
-//! # use bitcoin::*;
-//! # use bdk::wallet::{self, ChangeSet, coin_selection::*, coin_selection};
-//! # use bdk::wallet::error::CreateTxError;
-//! # use bdk_persist::PersistBackend;
-//! # use bdk::*;
-//! # use bdk::wallet::coin_selection::decide_change;
-//! # use anyhow::Error;
-//! #[derive(Debug)]
-//! struct AlwaysSpendEverything;
-//!
-//! impl CoinSelectionAlgorithm for AlwaysSpendEverything {
-//!     fn coin_select(
-//!         &self,
-//!         required_utxos: Vec<WeightedUtxo>,
-//!         optional_utxos: Vec<WeightedUtxo>,
-//!         fee_rate: FeeRate,
-//!         target_amount: u64,
-//!         drain_script: &Script,
-//!     ) -> Result<CoinSelectionResult, coin_selection::Error> {
-//!         let mut selected_amount = 0;
-//!         let mut additional_weight = Weight::ZERO;
-//!         let all_utxos_selected = required_utxos
-//!             .into_iter()
-//!             .chain(optional_utxos)
-//!             .scan(
-//!                 (&mut selected_amount, &mut additional_weight),
-//!                 |(selected_amount, additional_weight), weighted_utxo| {
-//!                     **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
-//!                     **additional_weight += Weight::from_wu(
-//!                         (TxIn::default().segwit_weight().to_wu()
-//!                             + weighted_utxo.satisfaction_weight as u64)
-//!                             as u64,
-//!                     );
-//!                     Some(weighted_utxo.utxo)
-//!                 },
-//!             )
-//!             .collect::<Vec<_>>();
-//!         let additional_fees = (fee_rate * additional_weight).to_sat();
-//!         let amount_needed_with_fees = additional_fees + target_amount;
-//!         if selected_amount < amount_needed_with_fees {
-//!             return Err(coin_selection::Error::InsufficientFunds {
-//!                 needed: amount_needed_with_fees,
-//!                 available: selected_amount,
-//!             });
-//!         }
-//!
-//!         let remaining_amount = selected_amount - amount_needed_with_fees;
-//!
-//!         let excess = decide_change(remaining_amount, fee_rate, drain_script);
-//!
-//!         Ok(CoinSelectionResult {
-//!             selected: all_utxos_selected,
-//!             fee_amount: additional_fees,
-//!             excess,
-//!         })
-//!     }
-//! }
-//!
-//! # let mut wallet = doctest_wallet!();
-//! // create wallet, sync, ...
-//!
-//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
-//!     .unwrap()
-//!     .require_network(Network::Testnet)
-//!     .unwrap();
-//! let psbt = {
-//!     let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
-//!     builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
-//!     builder.finish()?
-//! };
-//!
-//! // inspect, sign, broadcast, ...
-//!
-//! # Ok::<(), anyhow::Error>(())
-//! ```
-
-use crate::chain::collections::HashSet;
-use crate::wallet::utils::IsDust;
-use crate::Utxo;
-use crate::WeightedUtxo;
-use bitcoin::FeeRate;
-
-use alloc::vec::Vec;
-use bitcoin::consensus::encode::serialize;
-use bitcoin::OutPoint;
-use bitcoin::TxIn;
-use bitcoin::{Script, Weight};
-
-use core::convert::TryInto;
-use core::fmt::{self, Formatter};
-use rand::seq::SliceRandom;
-
-/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
-/// overridden
-pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
-
-/// Errors that can be thrown by the [`coin_selection`](crate::wallet::coin_selection) module
-#[derive(Debug)]
-pub enum Error {
-    /// Wallet's UTXO set is not enough to cover recipient's requested plus fee
-    InsufficientFunds {
-        /// Sats needed for some transaction
-        needed: u64,
-        /// Sats available for spending
-        available: u64,
-    },
-    /// Branch and bound coin selection tries to avoid needing a change by finding the right inputs for
-    /// the desired outputs plus fee, if there is not such combination this error is thrown
-    BnBNoExactMatch,
-    /// Branch and bound coin selection possible attempts with sufficiently big UTXO set could grow
-    /// exponentially, thus a limit is set, and when hit, this error is thrown
-    BnBTotalTriesExceeded,
-}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::InsufficientFunds { needed, available } => write!(
-                f,
-                "Insufficient funds: {} sat available of {} sat needed",
-                available, needed
-            ),
-            Self::BnBTotalTriesExceeded => {
-                write!(f, "Branch and bound coin selection: total tries exceeded")
-            }
-            Self::BnBNoExactMatch => write!(f, "Branch and bound coin selection: not exact match"),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for Error {}
-
-#[derive(Debug)]
-/// Remaining amount after performing coin selection
-pub enum Excess {
-    /// It's not possible to create spendable output from excess using the current drain output
-    NoChange {
-        /// Threshold to consider amount as dust for this particular change script_pubkey
-        dust_threshold: u64,
-        /// Exceeding amount of current selection over outgoing value and fee costs
-        remaining_amount: u64,
-        /// The calculated fee for the drain TxOut with the selected script_pubkey
-        change_fee: u64,
-    },
-    /// It's possible to create spendable output from excess using the current drain output
-    Change {
-        /// Effective amount available to create change after deducting the change output fee
-        amount: u64,
-        /// The deducted change output fee
-        fee: u64,
-    },
-}
-
-/// Result of a successful coin selection
-#[derive(Debug)]
-pub struct CoinSelectionResult {
-    /// List of outputs selected for use as inputs
-    pub selected: Vec<Utxo>,
-    /// Total fee amount for the selected utxos in satoshis
-    pub fee_amount: u64,
-    /// Remaining amount after deducing fees and outgoing outputs
-    pub excess: Excess,
-}
-
-impl CoinSelectionResult {
-    /// The total value of the inputs selected.
-    pub fn selected_amount(&self) -> u64 {
-        self.selected.iter().map(|u| u.txout().value.to_sat()).sum()
-    }
-
-    /// The total value of the inputs selected from the local wallet.
-    pub fn local_selected_amount(&self) -> u64 {
-        self.selected
-            .iter()
-            .filter_map(|u| match u {
-                Utxo::Local(_) => Some(u.txout().value.to_sat()),
-                _ => None,
-            })
-            .sum()
-    }
-}
-
-/// Trait for generalized coin selection algorithms
-///
-/// This trait can be implemented to make the [`Wallet`](super::Wallet) use a customized coin
-/// selection algorithm when it creates transactions.
-///
-/// For an example see [this module](crate::wallet::coin_selection)'s documentation.
-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
-    ///               details for a specific UTXO
-    /// - `required_utxos`: the utxos that must be spent regardless of `target_amount` with their
-    ///                     weight cost
-    /// - `optional_utxos`: the remaining available utxos to satisfy `target_amount` with their
-    ///                     weight cost
-    /// - `fee_rate`: fee rate to use
-    /// - `target_amount`: the outgoing amount in satoshis and the fees already
-    ///                    accumulated from added outputs and transaction’s header.
-    /// - `drain_script`: the script to use in case of change
-    #[allow(clippy::too_many_arguments)]
-    fn coin_select(
-        &self,
-        required_utxos: Vec<WeightedUtxo>,
-        optional_utxos: Vec<WeightedUtxo>,
-        fee_rate: FeeRate,
-        target_amount: u64,
-        drain_script: &Script,
-    ) -> Result<CoinSelectionResult, Error>;
-}
-
-/// 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.
-#[derive(Debug, Default, Clone, Copy)]
-pub struct LargestFirstCoinSelection;
-
-impl CoinSelectionAlgorithm for LargestFirstCoinSelection {
-    fn coin_select(
-        &self,
-        required_utxos: Vec<WeightedUtxo>,
-        mut optional_utxos: Vec<WeightedUtxo>,
-        fee_rate: FeeRate,
-        target_amount: u64,
-        drain_script: &Script,
-    ) -> Result<CoinSelectionResult, Error> {
-        // We put the "required UTXOs" first and make sure the optional UTXOs are sorted,
-        // initially smallest to largest, before being reversed with `.rev()`.
-        let utxos = {
-            optional_utxos.sort_unstable_by_key(|wu| wu.utxo.txout().value);
-            required_utxos
-                .into_iter()
-                .map(|utxo| (true, utxo))
-                .chain(optional_utxos.into_iter().rev().map(|utxo| (false, utxo)))
-        };
-
-        select_sorted_utxos(utxos, fee_rate, target_amount, drain_script)
-    }
-}
-
-/// 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.
-#[derive(Debug, Default, Clone, Copy)]
-pub struct OldestFirstCoinSelection;
-
-impl CoinSelectionAlgorithm for OldestFirstCoinSelection {
-    fn coin_select(
-        &self,
-        required_utxos: Vec<WeightedUtxo>,
-        mut optional_utxos: Vec<WeightedUtxo>,
-        fee_rate: FeeRate,
-        target_amount: u64,
-        drain_script: &Script,
-    ) -> Result<CoinSelectionResult, Error> {
-        // 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 &wu.utxo {
-                Utxo::Local(local) => Some(local.confirmation_time),
-                Utxo::Foreign { .. } => None,
-            });
-
-            required_utxos
-                .into_iter()
-                .map(|utxo| (true, utxo))
-                .chain(optional_utxos.into_iter().map(|utxo| (false, utxo)))
-        };
-
-        select_sorted_utxos(utxos, fee_rate, target_amount, drain_script)
-    }
-}
-
-/// Decide if change can be created
-///
-/// - `remaining_amount`: the amount in which the selected coins exceed the target amount
-/// - `fee_rate`: required fee rate for the current selection
-/// - `drain_script`: script to consider change creation
-pub fn decide_change(remaining_amount: u64, fee_rate: FeeRate, drain_script: &Script) -> Excess {
-    // drain_output_len = size(len(script_pubkey)) + len(script_pubkey) + size(output_value)
-    let drain_output_len = serialize(drain_script).len() + 8usize;
-    let change_fee =
-        (fee_rate * Weight::from_vb(drain_output_len as u64).expect("overflow occurred")).to_sat();
-    let drain_val = remaining_amount.saturating_sub(change_fee);
-
-    if drain_val.is_dust(drain_script) {
-        let dust_threshold = drain_script.dust_value().to_sat();
-        Excess::NoChange {
-            dust_threshold,
-            change_fee,
-            remaining_amount,
-        }
-    } else {
-        Excess::Change {
-            amount: drain_val,
-            fee: change_fee,
-        }
-    }
-}
-
-fn select_sorted_utxos(
-    utxos: impl Iterator<Item = (bool, WeightedUtxo)>,
-    fee_rate: FeeRate,
-    target_amount: u64,
-    drain_script: &Script,
-) -> Result<CoinSelectionResult, Error> {
-    let mut selected_amount = 0;
-    let mut fee_amount = 0;
-    let selected = utxos
-        .scan(
-            (&mut selected_amount, &mut fee_amount),
-            |(selected_amount, fee_amount), (must_use, weighted_utxo)| {
-                if must_use || **selected_amount < target_amount + **fee_amount {
-                    **fee_amount += (fee_rate
-                        * Weight::from_wu(
-                            TxIn::default().segwit_weight().to_wu()
-                                + weighted_utxo.satisfaction_weight as u64,
-                        ))
-                    .to_sat();
-                    **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
-                    Some(weighted_utxo.utxo)
-                } else {
-                    None
-                }
-            },
-        )
-        .collect::<Vec<_>>();
-
-    let amount_needed_with_fees = target_amount + fee_amount;
-    if selected_amount < amount_needed_with_fees {
-        return Err(Error::InsufficientFunds {
-            needed: amount_needed_with_fees,
-            available: selected_amount,
-        });
-    }
-
-    let remaining_amount = selected_amount - amount_needed_with_fees;
-
-    let excess = decide_change(remaining_amount, fee_rate, drain_script);
-
-    Ok(CoinSelectionResult {
-        selected,
-        fee_amount,
-        excess,
-    })
-}
-
-#[derive(Debug, Clone)]
-// Adds fee information to an UTXO.
-struct OutputGroup {
-    weighted_utxo: WeightedUtxo,
-    // Amount of fees for spending a certain utxo, calculated using a certain FeeRate
-    fee: u64,
-    // The effective value of the UTXO, i.e., the utxo value minus the fee for spending it
-    effective_value: i64,
-}
-
-impl OutputGroup {
-    fn new(weighted_utxo: WeightedUtxo, fee_rate: FeeRate) -> Self {
-        let fee = (fee_rate
-            * Weight::from_wu(
-                TxIn::default().segwit_weight().to_wu() + weighted_utxo.satisfaction_weight as u64,
-            ))
-        .to_sat();
-        let effective_value = weighted_utxo.utxo.txout().value.to_sat() as i64 - fee as i64;
-        OutputGroup {
-            weighted_utxo,
-            fee,
-            effective_value,
-        }
-    }
-}
-
-/// 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, Clone)]
-pub struct BranchAndBoundCoinSelection {
-    size_of_change: u64,
-}
-
-impl Default for BranchAndBoundCoinSelection {
-    fn default() -> Self {
-        Self {
-            // P2WPKH cost of change -> value (8 bytes) + script len (1 bytes) + script (22 bytes)
-            size_of_change: 8 + 1 + 22,
-        }
-    }
-}
-
-impl BranchAndBoundCoinSelection {
-    /// Create new instance with target size for change output
-    pub fn new(size_of_change: u64) -> Self {
-        Self { size_of_change }
-    }
-}
-
-const BNB_TOTAL_TRIES: usize = 100_000;
-
-impl CoinSelectionAlgorithm for BranchAndBoundCoinSelection {
-    fn coin_select(
-        &self,
-        required_utxos: Vec<WeightedUtxo>,
-        optional_utxos: Vec<WeightedUtxo>,
-        fee_rate: FeeRate,
-        target_amount: u64,
-        drain_script: &Script,
-    ) -> Result<CoinSelectionResult, Error> {
-        // Mapping every (UTXO, usize) to an output group
-        let required_utxos: Vec<OutputGroup> = required_utxos
-            .into_iter()
-            .map(|u| OutputGroup::new(u, fee_rate))
-            .collect();
-
-        // Mapping every (UTXO, usize) to an output group, filtering UTXOs with a negative
-        // effective value
-        let optional_utxos: Vec<OutputGroup> = optional_utxos
-            .into_iter()
-            .map(|u| OutputGroup::new(u, fee_rate))
-            .filter(|u| u.effective_value.is_positive())
-            .collect();
-
-        let curr_value = required_utxos
-            .iter()
-            .fold(0, |acc, x| acc + x.effective_value);
-
-        let curr_available_value = optional_utxos
-            .iter()
-            .fold(0, |acc, x| acc + x.effective_value);
-
-        let cost_of_change =
-            (Weight::from_vb(self.size_of_change).expect("overflow occurred") * fee_rate).to_sat();
-
-        // `curr_value` and `curr_available_value` are both the sum of *effective_values* of
-        // the UTXOs. For the optional UTXOs (curr_available_value) we filter out UTXOs with
-        // negative effective value, so it will always be positive.
-        //
-        // Since we are required to spend the required UTXOs (curr_value) we have to consider
-        // all their effective values, even when negative, which means that curr_value could
-        // be negative as well.
-        //
-        // If the sum of curr_value and curr_available_value is negative or lower than our target,
-        // we can immediately exit with an error, as it's guaranteed we will never find a solution
-        // if we actually run the BnB.
-        let total_value: Result<u64, _> = (curr_available_value + curr_value).try_into();
-        match total_value {
-            Ok(v) if v >= target_amount => {}
-            _ => {
-                // Assume we spend all the UTXOs we can (all the required + all the optional with
-                // positive effective value), sum their value and their fee cost.
-                let (utxo_fees, utxo_value) = required_utxos
-                    .iter()
-                    .chain(optional_utxos.iter())
-                    .fold((0, 0), |(mut fees, mut value), utxo| {
-                        fees += utxo.fee;
-                        value += utxo.weighted_utxo.utxo.txout().value.to_sat();
-
-                        (fees, value)
-                    });
-
-                // Add to the target the fee cost of the UTXOs
-                return Err(Error::InsufficientFunds {
-                    needed: target_amount + utxo_fees,
-                    available: utxo_value,
-                });
-            }
-        }
-
-        let target_amount = target_amount
-            .try_into()
-            .expect("Bitcoin amount to fit into i64");
-
-        if curr_value > target_amount {
-            // remaining_amount can't be negative as that would mean the
-            // selection wasn't successful
-            // target_amount = amount_needed + (fee_amount - vin_fees)
-            let remaining_amount = (curr_value - target_amount) as u64;
-
-            let excess = decide_change(remaining_amount, fee_rate, drain_script);
-
-            return Ok(BranchAndBoundCoinSelection::calculate_cs_result(
-                vec![],
-                required_utxos,
-                excess,
-            ));
-        }
-
-        Ok(self
-            .bnb(
-                required_utxos.clone(),
-                optional_utxos.clone(),
-                curr_value,
-                curr_available_value,
-                target_amount,
-                cost_of_change,
-                drain_script,
-                fee_rate,
-            )
-            .unwrap_or_else(|_| {
-                self.single_random_draw(
-                    required_utxos,
-                    optional_utxos,
-                    curr_value,
-                    target_amount,
-                    drain_script,
-                    fee_rate,
-                )
-            }))
-    }
-}
-
-impl BranchAndBoundCoinSelection {
-    // TODO: make this more Rust-onic :)
-    // (And perhaps refactor with less arguments?)
-    #[allow(clippy::too_many_arguments)]
-    fn bnb(
-        &self,
-        required_utxos: Vec<OutputGroup>,
-        mut optional_utxos: Vec<OutputGroup>,
-        mut curr_value: i64,
-        mut curr_available_value: i64,
-        target_amount: i64,
-        cost_of_change: u64,
-        drain_script: &Script,
-        fee_rate: FeeRate,
-    ) -> Result<CoinSelectionResult, Error> {
-        // current_selection[i] will contain true if we are using optional_utxos[i],
-        // false otherwise. Note that current_selection.len() could be less than
-        // optional_utxos.len(), it just means that we still haven't decided if we should keep
-        // certain optional_utxos or not.
-        let mut current_selection: Vec<bool> = Vec::with_capacity(optional_utxos.len());
-
-        // Sort the utxo_pool
-        optional_utxos.sort_unstable_by_key(|a| a.effective_value);
-        optional_utxos.reverse();
-
-        // Contains the best selection we found
-        let mut best_selection = Vec::new();
-        let mut best_selection_value = None;
-
-        // Depth First search loop for choosing the UTXOs
-        for _ in 0..BNB_TOTAL_TRIES {
-            // Conditions for starting a backtrack
-            let mut backtrack = false;
-            // Cannot possibly reach target with the amount remaining in the curr_available_value,
-            // or the selected value is out of range.
-            // Go back and try other branch
-            if curr_value + curr_available_value < target_amount
-                || curr_value > target_amount + cost_of_change as i64
-            {
-                backtrack = true;
-            } else if curr_value >= target_amount {
-                // Selected value is within range, there's no point in going forward. Start
-                // backtracking
-                backtrack = true;
-
-                // If we found a solution better than the previous one, or if there wasn't previous
-                // solution, update the best solution
-                if best_selection_value.is_none() || curr_value < best_selection_value.unwrap() {
-                    best_selection.clone_from(&current_selection);
-                    best_selection_value = Some(curr_value);
-                }
-
-                // If we found a perfect match, break here
-                if curr_value == target_amount {
-                    break;
-                }
-            }
-
-            // Backtracking, moving backwards
-            if backtrack {
-                // Walk backwards to find the last included UTXO that still needs to have its omission branch traversed.
-                while let Some(false) = current_selection.last() {
-                    current_selection.pop();
-                    curr_available_value += optional_utxos[current_selection.len()].effective_value;
-                }
-
-                if current_selection.last_mut().is_none() {
-                    // We have walked back to the first utxo and no branch is untraversed. All solutions searched
-                    // If best selection is empty, then there's no exact match
-                    if best_selection.is_empty() {
-                        return Err(Error::BnBNoExactMatch);
-                    }
-                    break;
-                }
-
-                if let Some(c) = current_selection.last_mut() {
-                    // Output was included on previous iterations, try excluding now.
-                    *c = false;
-                }
-
-                let utxo = &optional_utxos[current_selection.len() - 1];
-                curr_value -= utxo.effective_value;
-            } else {
-                // Moving forwards, continuing down this branch
-                let utxo = &optional_utxos[current_selection.len()];
-
-                // Remove this utxo from the curr_available_value utxo amount
-                curr_available_value -= utxo.effective_value;
-
-                // Inclusion branch first (Largest First Exploration)
-                current_selection.push(true);
-                curr_value += utxo.effective_value;
-            }
-        }
-
-        // Check for solution
-        if best_selection.is_empty() {
-            return Err(Error::BnBTotalTriesExceeded);
-        }
-
-        // Set output set
-        let selected_utxos = optional_utxos
-            .into_iter()
-            .zip(best_selection)
-            .filter_map(|(optional, is_in_best)| if is_in_best { Some(optional) } else { None })
-            .collect::<Vec<OutputGroup>>();
-
-        let selected_amount = best_selection_value.unwrap();
-
-        // remaining_amount can't be negative as that would mean the
-        // selection wasn't successful
-        // target_amount = amount_needed + (fee_amount - vin_fees)
-        let remaining_amount = (selected_amount - target_amount) as u64;
-
-        let excess = decide_change(remaining_amount, fee_rate, drain_script);
-
-        Ok(BranchAndBoundCoinSelection::calculate_cs_result(
-            selected_utxos,
-            required_utxos,
-            excess,
-        ))
-    }
-
-    #[allow(clippy::too_many_arguments)]
-    fn single_random_draw(
-        &self,
-        required_utxos: Vec<OutputGroup>,
-        mut optional_utxos: Vec<OutputGroup>,
-        curr_value: i64,
-        target_amount: i64,
-        drain_script: &Script,
-        fee_rate: FeeRate,
-    ) -> CoinSelectionResult {
-        optional_utxos.shuffle(&mut rand::thread_rng());
-        let selected_utxos = optional_utxos.into_iter().fold(
-            (curr_value, vec![]),
-            |(mut amount, mut utxos), utxo| {
-                if amount >= target_amount {
-                    (amount, utxos)
-                } else {
-                    amount += utxo.effective_value;
-                    utxos.push(utxo);
-                    (amount, utxos)
-                }
-            },
-        );
-
-        // remaining_amount can't be negative as that would mean the
-        // selection wasn't successful
-        // target_amount = amount_needed + (fee_amount - vin_fees)
-        let remaining_amount = (selected_utxos.0 - target_amount) as u64;
-
-        let excess = decide_change(remaining_amount, fee_rate, drain_script);
-
-        BranchAndBoundCoinSelection::calculate_cs_result(selected_utxos.1, required_utxos, excess)
-    }
-
-    fn calculate_cs_result(
-        mut selected_utxos: Vec<OutputGroup>,
-        mut required_utxos: Vec<OutputGroup>,
-        excess: Excess,
-    ) -> CoinSelectionResult {
-        selected_utxos.append(&mut required_utxos);
-        let fee_amount = selected_utxos.iter().map(|u| u.fee).sum::<u64>();
-        let selected = selected_utxos
-            .into_iter()
-            .map(|u| u.weighted_utxo.utxo)
-            .collect::<Vec<_>>();
-
-        CoinSelectionResult {
-            selected,
-            fee_amount,
-            excess,
-        }
-    }
-}
-
-/// Remove duplicate UTXOs.
-///
-/// If a UTXO appears in both `required` and `optional`, the appearance in `required` is kept.
-pub(crate) fn filter_duplicates<I>(required: I, optional: I) -> (I, I)
-where
-    I: IntoIterator<Item = WeightedUtxo> + FromIterator<WeightedUtxo>,
-{
-    let mut visited = HashSet::<OutPoint>::new();
-    let required = required
-        .into_iter()
-        .filter(|utxo| visited.insert(utxo.utxo.outpoint()))
-        .collect::<I>();
-    let optional = optional
-        .into_iter()
-        .filter(|utxo| visited.insert(utxo.utxo.outpoint()))
-        .collect::<I>();
-    (required, optional)
-}
-
-#[cfg(test)]
-mod test {
-    use assert_matches::assert_matches;
-    use core::str::FromStr;
-
-    use bdk_chain::ConfirmationTime;
-    use bitcoin::{Amount, ScriptBuf, TxIn, TxOut};
-
-    use super::*;
-    use crate::types::*;
-    use crate::wallet::coin_selection::filter_duplicates;
-
-    use rand::rngs::StdRng;
-    use rand::seq::SliceRandom;
-    use rand::{Rng, RngCore, SeedableRng};
-
-    // signature len (1WU) + signature and sighash (72WU)
-    // + pubkey len (1WU) + pubkey (33WU)
-    const P2WPKH_SATISFACTION_SIZE: usize = 1 + 72 + 1 + 33;
-
-    const FEE_AMOUNT: u64 = 50;
-
-    fn utxo(value: u64, index: u32, confirmation_time: ConfirmationTime) -> WeightedUtxo {
-        assert!(index < 10);
-        let outpoint = OutPoint::from_str(&format!(
-            "000000000000000000000000000000000000000000000000000000000000000{}:0",
-            index
-        ))
-        .unwrap();
-        WeightedUtxo {
-            satisfaction_weight: P2WPKH_SATISFACTION_SIZE,
-            utxo: Utxo::Local(LocalOutput {
-                outpoint,
-                txout: TxOut {
-                    value: Amount::from_sat(value),
-                    script_pubkey: ScriptBuf::new(),
-                },
-                keychain: KeychainKind::External,
-                is_spent: false,
-                derivation_index: 42,
-                confirmation_time,
-            }),
-        }
-    }
-
-    fn get_test_utxos() -> Vec<WeightedUtxo> {
-        vec![
-            utxo(100_000, 0, ConfirmationTime::Unconfirmed { last_seen: 0 }),
-            utxo(
-                FEE_AMOUNT - 40,
-                1,
-                ConfirmationTime::Unconfirmed { last_seen: 0 },
-            ),
-            utxo(200_000, 2, ConfirmationTime::Unconfirmed { last_seen: 0 }),
-        ]
-    }
-
-    fn get_oldest_first_test_utxos() -> Vec<WeightedUtxo> {
-        // ensure utxos are from different tx
-        let utxo1 = utxo(
-            120_000,
-            1,
-            ConfirmationTime::Confirmed {
-                height: 1,
-                time: 1231006505,
-            },
-        );
-        let utxo2 = utxo(
-            80_000,
-            2,
-            ConfirmationTime::Confirmed {
-                height: 2,
-                time: 1231006505,
-            },
-        );
-        let utxo3 = utxo(
-            300_000,
-            3,
-            ConfirmationTime::Confirmed {
-                height: 3,
-                time: 1231006505,
-            },
-        );
-        vec![utxo1, utxo2, utxo3]
-    }
-
-    fn generate_random_utxos(rng: &mut StdRng, utxos_number: usize) -> Vec<WeightedUtxo> {
-        let mut res = Vec::new();
-        for i in 0..utxos_number {
-            res.push(WeightedUtxo {
-                satisfaction_weight: P2WPKH_SATISFACTION_SIZE,
-                utxo: Utxo::Local(LocalOutput {
-                    outpoint: OutPoint::from_str(&format!(
-                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:{}",
-                        i
-                    ))
-                    .unwrap(),
-                    txout: TxOut {
-                        value: Amount::from_sat(rng.gen_range(0..200000000)),
-                        script_pubkey: ScriptBuf::new(),
-                    },
-                    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 { last_seen: 0 }
-                    },
-                }),
-            });
-        }
-        res
-    }
-
-    fn generate_same_value_utxos(utxos_value: u64, utxos_number: usize) -> Vec<WeightedUtxo> {
-        (0..utxos_number)
-            .map(|i| WeightedUtxo {
-                satisfaction_weight: P2WPKH_SATISFACTION_SIZE,
-                utxo: Utxo::Local(LocalOutput {
-                    outpoint: OutPoint::from_str(&format!(
-                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:{}",
-                        i
-                    ))
-                    .unwrap(),
-                    txout: TxOut {
-                        value: Amount::from_sat(utxos_value),
-                        script_pubkey: ScriptBuf::new(),
-                    },
-                    keychain: KeychainKind::External,
-                    is_spent: false,
-                    derivation_index: 42,
-                    confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 },
-                }),
-            })
-            .collect()
-    }
-
-    fn sum_random_utxos(mut rng: &mut StdRng, utxos: &mut Vec<WeightedUtxo>) -> u64 {
-        let utxos_picked_len = rng.gen_range(2..utxos.len() / 2);
-        utxos.shuffle(&mut rng);
-        utxos[..utxos_picked_len]
-            .iter()
-            .map(|u| u.utxo.txout().value.to_sat())
-            .sum()
-    }
-
-    #[test]
-    fn test_largest_first_coin_selection_success() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 250_000 + FEE_AMOUNT;
-
-        let result = LargestFirstCoinSelection
-            .coin_select(
-                utxos,
-                vec![],
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 3);
-        assert_eq!(result.selected_amount(), 300_010);
-        assert_eq!(result.fee_amount, 204)
-    }
-
-    #[test]
-    fn test_largest_first_coin_selection_use_all() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 20_000 + FEE_AMOUNT;
-
-        let result = LargestFirstCoinSelection
-            .coin_select(
-                utxos,
-                vec![],
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 3);
-        assert_eq!(result.selected_amount(), 300_010);
-        assert_eq!(result.fee_amount, 204);
-    }
-
-    #[test]
-    fn test_largest_first_coin_selection_use_only_necessary() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 20_000 + FEE_AMOUNT;
-
-        let result = LargestFirstCoinSelection
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 1);
-        assert_eq!(result.selected_amount(), 200_000);
-        assert_eq!(result.fee_amount, 68);
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_largest_first_coin_selection_insufficient_funds() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 500_000 + FEE_AMOUNT;
-
-        LargestFirstCoinSelection
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_largest_first_coin_selection_insufficient_funds_high_fees() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 250_000 + FEE_AMOUNT;
-
-        LargestFirstCoinSelection
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1000),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_oldest_first_coin_selection_success() {
-        let utxos = get_oldest_first_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 180_000 + FEE_AMOUNT;
-
-        let result = OldestFirstCoinSelection
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                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 utxos = get_oldest_first_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 20_000 + FEE_AMOUNT;
-
-        let result = OldestFirstCoinSelection
-            .coin_select(
-                utxos,
-                vec![],
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 3);
-        assert_eq!(result.selected_amount(), 500_000);
-        assert_eq!(result.fee_amount, 204);
-    }
-
-    #[test]
-    fn test_oldest_first_coin_selection_use_only_necessary() {
-        let utxos = get_oldest_first_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 20_000 + FEE_AMOUNT;
-
-        let result = OldestFirstCoinSelection
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 1);
-        assert_eq!(result.selected_amount(), 120_000);
-        assert_eq!(result.fee_amount, 68);
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_oldest_first_coin_selection_insufficient_funds() {
-        let utxos = get_oldest_first_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 600_000 + FEE_AMOUNT;
-
-        OldestFirstCoinSelection
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_oldest_first_coin_selection_insufficient_funds_high_fees() {
-        let utxos = get_oldest_first_test_utxos();
-
-        let target_amount: u64 = utxos
-            .iter()
-            .map(|wu| wu.utxo.txout().value.to_sat())
-            .sum::<u64>()
-            - 50;
-        let drain_script = ScriptBuf::default();
-
-        OldestFirstCoinSelection
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1000),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_bnb_coin_selection_success() {
-        // In this case bnb won't find a suitable match and single random draw will
-        // select three outputs
-        let utxos = generate_same_value_utxos(100_000, 20);
-
-        let drain_script = ScriptBuf::default();
-
-        let target_amount = 250_000 + FEE_AMOUNT;
-
-        let result = BranchAndBoundCoinSelection::default()
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 3);
-        assert_eq!(result.selected_amount(), 300_000);
-        assert_eq!(result.fee_amount, 204);
-    }
-
-    #[test]
-    fn test_bnb_coin_selection_required_are_enough() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 20_000 + FEE_AMOUNT;
-
-        let result = BranchAndBoundCoinSelection::default()
-            .coin_select(
-                utxos.clone(),
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 3);
-        assert_eq!(result.selected_amount(), 300_010);
-        assert_eq!(result.fee_amount, 204);
-    }
-
-    #[test]
-    fn test_bnb_coin_selection_optional_are_enough() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 299756 + FEE_AMOUNT;
-
-        let result = BranchAndBoundCoinSelection::default()
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 2);
-        assert_eq!(result.selected_amount(), 300000);
-        assert_eq!(result.fee_amount, 136);
-    }
-
-    #[test]
-    #[ignore]
-    fn test_bnb_coin_selection_required_not_enough() {
-        let utxos = get_test_utxos();
-
-        let required = vec![utxos[0].clone()];
-        let mut optional = utxos[1..].to_vec();
-        optional.push(utxo(
-            500_000,
-            3,
-            ConfirmationTime::Unconfirmed { last_seen: 0 },
-        ));
-
-        // Defensive assertions, for sanity and in case someone changes the test utxos vector.
-        let amount: u64 = required.iter().map(|u| u.utxo.txout().value.to_sat()).sum();
-        assert_eq!(amount, 100_000);
-        let amount: u64 = optional.iter().map(|u| u.utxo.txout().value.to_sat()).sum();
-        assert!(amount > 150_000);
-        let drain_script = ScriptBuf::default();
-
-        let target_amount = 150_000 + FEE_AMOUNT;
-
-        let result = BranchAndBoundCoinSelection::default()
-            .coin_select(
-                required,
-                optional,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 2);
-        assert_eq!(result.selected_amount(), 300_000);
-        assert_eq!(result.fee_amount, 136);
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_bnb_coin_selection_insufficient_funds() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 500_000 + FEE_AMOUNT;
-
-        BranchAndBoundCoinSelection::default()
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "InsufficientFunds")]
-    fn test_bnb_coin_selection_insufficient_funds_high_fees() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 250_000 + FEE_AMOUNT;
-
-        BranchAndBoundCoinSelection::default()
-            .coin_select(
-                vec![],
-                utxos,
-                FeeRate::from_sat_per_vb_unchecked(1000),
-                target_amount,
-                &drain_script,
-            )
-            .unwrap();
-    }
-
-    #[test]
-    fn test_bnb_coin_selection_check_fee_rate() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-        let target_amount = 99932; // first utxo's effective value
-        let feerate = FeeRate::BROADCAST_MIN;
-
-        let result = BranchAndBoundCoinSelection::new(0)
-            .coin_select(vec![], utxos, feerate, target_amount, &drain_script)
-            .unwrap();
-
-        assert_eq!(result.selected.len(), 1);
-        assert_eq!(result.selected_amount(), 100_000);
-        let input_weight =
-            TxIn::default().segwit_weight().to_wu() + P2WPKH_SATISFACTION_SIZE as u64;
-        // the final fee rate should be exactly the same as the fee rate given
-        let result_feerate = Amount::from_sat(result.fee_amount) / Weight::from_wu(input_weight);
-        assert_eq!(result_feerate, feerate);
-    }
-
-    #[test]
-    fn test_bnb_coin_selection_exact_match() {
-        let seed = [0; 32];
-        let mut rng: StdRng = SeedableRng::from_seed(seed);
-
-        for _i in 0..200 {
-            let mut optional_utxos = generate_random_utxos(&mut rng, 16);
-            let target_amount = sum_random_utxos(&mut rng, &mut optional_utxos);
-            let drain_script = ScriptBuf::default();
-            let result = BranchAndBoundCoinSelection::new(0)
-                .coin_select(
-                    vec![],
-                    optional_utxos,
-                    FeeRate::ZERO,
-                    target_amount,
-                    &drain_script,
-                )
-                .unwrap();
-            assert_eq!(result.selected_amount(), target_amount);
-        }
-    }
-
-    #[test]
-    #[should_panic(expected = "BnBNoExactMatch")]
-    fn test_bnb_function_no_exact_match() {
-        let fee_rate = FeeRate::from_sat_per_vb_unchecked(10);
-        let utxos: Vec<OutputGroup> = get_test_utxos()
-            .into_iter()
-            .map(|u| OutputGroup::new(u, fee_rate))
-            .collect();
-
-        let curr_available_value = utxos.iter().fold(0, |acc, x| acc + x.effective_value);
-
-        let size_of_change = 31;
-        let cost_of_change = (Weight::from_vb_unchecked(size_of_change) * fee_rate).to_sat();
-
-        let drain_script = ScriptBuf::default();
-        let target_amount = 20_000 + FEE_AMOUNT;
-        BranchAndBoundCoinSelection::new(size_of_change)
-            .bnb(
-                vec![],
-                utxos,
-                0,
-                curr_available_value,
-                target_amount as i64,
-                cost_of_change,
-                &drain_script,
-                fee_rate,
-            )
-            .unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "BnBTotalTriesExceeded")]
-    fn test_bnb_function_tries_exceeded() {
-        let fee_rate = FeeRate::from_sat_per_vb_unchecked(10);
-        let utxos: Vec<OutputGroup> = generate_same_value_utxos(100_000, 100_000)
-            .into_iter()
-            .map(|u| OutputGroup::new(u, fee_rate))
-            .collect();
-
-        let curr_available_value = utxos.iter().fold(0, |acc, x| acc + x.effective_value);
-
-        let size_of_change = 31;
-        let cost_of_change = (Weight::from_vb_unchecked(size_of_change) * fee_rate).to_sat();
-        let target_amount = 20_000 + FEE_AMOUNT;
-
-        let drain_script = ScriptBuf::default();
-
-        BranchAndBoundCoinSelection::new(size_of_change)
-            .bnb(
-                vec![],
-                utxos,
-                0,
-                curr_available_value,
-                target_amount as i64,
-                cost_of_change,
-                &drain_script,
-                fee_rate,
-            )
-            .unwrap();
-    }
-
-    // The match won't be exact but still in the range
-    #[test]
-    fn test_bnb_function_almost_exact_match_with_fees() {
-        let fee_rate = FeeRate::from_sat_per_vb_unchecked(1);
-        let size_of_change = 31;
-        let cost_of_change = (Weight::from_vb_unchecked(size_of_change) * fee_rate).to_sat();
-
-        let utxos: Vec<_> = generate_same_value_utxos(50_000, 10)
-            .into_iter()
-            .map(|u| OutputGroup::new(u, fee_rate))
-            .collect();
-
-        let curr_value = 0;
-
-        let curr_available_value = utxos.iter().fold(0, |acc, x| acc + x.effective_value);
-
-        // 2*(value of 1 utxo)  - 2*(1 utxo fees with 1.0sat/vbyte fee rate) -
-        // cost_of_change + 5.
-        let target_amount = 2 * 50_000 - 2 * 67 - cost_of_change as i64 + 5;
-
-        let drain_script = ScriptBuf::default();
-
-        let result = BranchAndBoundCoinSelection::new(size_of_change)
-            .bnb(
-                vec![],
-                utxos,
-                curr_value,
-                curr_available_value,
-                target_amount,
-                cost_of_change,
-                &drain_script,
-                fee_rate,
-            )
-            .unwrap();
-        assert_eq!(result.selected_amount(), 100_000);
-        assert_eq!(result.fee_amount, 136);
-    }
-
-    // TODO: bnb() function should be optimized, and this test should be done with more utxos
-    #[test]
-    fn test_bnb_function_exact_match_more_utxos() {
-        let seed = [0; 32];
-        let mut rng: StdRng = SeedableRng::from_seed(seed);
-        let fee_rate = FeeRate::ZERO;
-
-        for _ in 0..200 {
-            let optional_utxos: Vec<_> = generate_random_utxos(&mut rng, 40)
-                .into_iter()
-                .map(|u| OutputGroup::new(u, fee_rate))
-                .collect();
-
-            let curr_value = 0;
-
-            let curr_available_value = optional_utxos
-                .iter()
-                .fold(0, |acc, x| acc + x.effective_value);
-
-            let target_amount =
-                optional_utxos[3].effective_value + optional_utxos[23].effective_value;
-
-            let drain_script = ScriptBuf::default();
-
-            let result = BranchAndBoundCoinSelection::new(0)
-                .bnb(
-                    vec![],
-                    optional_utxos,
-                    curr_value,
-                    curr_available_value,
-                    target_amount,
-                    0,
-                    &drain_script,
-                    fee_rate,
-                )
-                .unwrap();
-            assert_eq!(result.selected_amount(), target_amount as u64);
-        }
-    }
-
-    #[test]
-    fn test_single_random_draw_function_success() {
-        let seed = [0; 32];
-        let mut rng: StdRng = SeedableRng::from_seed(seed);
-        let mut utxos = generate_random_utxos(&mut rng, 300);
-        let target_amount = sum_random_utxos(&mut rng, &mut utxos) + FEE_AMOUNT;
-
-        let fee_rate = FeeRate::from_sat_per_vb_unchecked(1);
-        let utxos: Vec<OutputGroup> = utxos
-            .into_iter()
-            .map(|u| OutputGroup::new(u, fee_rate))
-            .collect();
-
-        let drain_script = ScriptBuf::default();
-
-        let result = BranchAndBoundCoinSelection::default().single_random_draw(
-            vec![],
-            utxos,
-            0,
-            target_amount as i64,
-            &drain_script,
-            fee_rate,
-        );
-
-        assert!(result.selected_amount() > target_amount);
-        assert_eq!(result.fee_amount, (result.selected.len() * 68) as u64);
-    }
-
-    #[test]
-    fn test_bnb_exclude_negative_effective_value() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-
-        let selection = BranchAndBoundCoinSelection::default().coin_select(
-            vec![],
-            utxos,
-            FeeRate::from_sat_per_vb_unchecked(10),
-            500_000,
-            &drain_script,
-        );
-
-        assert_matches!(
-            selection,
-            Err(Error::InsufficientFunds {
-                available: 300_000,
-                ..
-            })
-        );
-    }
-
-    #[test]
-    fn test_bnb_include_negative_effective_value_when_required() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-
-        let (required, optional) = utxos.into_iter().partition(
-            |u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value.to_sat() < 1000),
-        );
-
-        let selection = BranchAndBoundCoinSelection::default().coin_select(
-            required,
-            optional,
-            FeeRate::from_sat_per_vb_unchecked(10),
-            500_000,
-            &drain_script,
-        );
-
-        assert_matches!(
-            selection,
-            Err(Error::InsufficientFunds {
-                available: 300_010,
-                ..
-            })
-        );
-    }
-
-    #[test]
-    fn test_bnb_sum_of_effective_value_negative() {
-        let utxos = get_test_utxos();
-        let drain_script = ScriptBuf::default();
-
-        let selection = BranchAndBoundCoinSelection::default().coin_select(
-            utxos,
-            vec![],
-            FeeRate::from_sat_per_vb_unchecked(10_000),
-            500_000,
-            &drain_script,
-        );
-
-        assert_matches!(
-            selection,
-            Err(Error::InsufficientFunds {
-                available: 300_010,
-                ..
-            })
-        );
-    }
-
-    #[test]
-    fn test_filter_duplicates() {
-        fn utxo(txid: &str, value: u64) -> WeightedUtxo {
-            WeightedUtxo {
-                satisfaction_weight: 0,
-                utxo: Utxo::Local(LocalOutput {
-                    outpoint: OutPoint::new(bitcoin::hashes::Hash::hash(txid.as_bytes()), 0),
-                    txout: TxOut {
-                        value: Amount::from_sat(value),
-                        script_pubkey: ScriptBuf::new(),
-                    },
-                    keychain: KeychainKind::External,
-                    is_spent: false,
-                    derivation_index: 0,
-                    confirmation_time: ConfirmationTime::Confirmed {
-                        height: 12345,
-                        time: 12345,
-                    },
-                }),
-            }
-        }
-
-        fn to_utxo_vec(utxos: &[(&str, u64)]) -> Vec<WeightedUtxo> {
-            let mut v = utxos
-                .iter()
-                .map(|&(txid, value)| utxo(txid, value))
-                .collect::<Vec<_>>();
-            v.sort_by_key(|u| u.utxo.outpoint());
-            v
-        }
-
-        struct TestCase<'a> {
-            name: &'a str,
-            required: &'a [(&'a str, u64)],
-            optional: &'a [(&'a str, u64)],
-            exp_required: &'a [(&'a str, u64)],
-            exp_optional: &'a [(&'a str, u64)],
-        }
-
-        let test_cases = [
-            TestCase {
-                name: "no_duplicates",
-                required: &[("A", 1000), ("B", 2100)],
-                optional: &[("C", 1000)],
-                exp_required: &[("A", 1000), ("B", 2100)],
-                exp_optional: &[("C", 1000)],
-            },
-            TestCase {
-                name: "duplicate_required_utxos",
-                required: &[("A", 3000), ("B", 1200), ("C", 1234), ("A", 3000)],
-                optional: &[("D", 2100)],
-                exp_required: &[("A", 3000), ("B", 1200), ("C", 1234)],
-                exp_optional: &[("D", 2100)],
-            },
-            TestCase {
-                name: "duplicate_optional_utxos",
-                required: &[("A", 3000), ("B", 1200)],
-                optional: &[("C", 5000), ("D", 1300), ("C", 5000)],
-                exp_required: &[("A", 3000), ("B", 1200)],
-                exp_optional: &[("C", 5000), ("D", 1300)],
-            },
-            TestCase {
-                name: "duplicate_across_required_and_optional_utxos",
-                required: &[("A", 3000), ("B", 1200), ("C", 2100)],
-                optional: &[("A", 3000), ("D", 1200), ("E", 5000)],
-                exp_required: &[("A", 3000), ("B", 1200), ("C", 2100)],
-                exp_optional: &[("D", 1200), ("E", 5000)],
-            },
-        ];
-
-        for (i, t) in test_cases.into_iter().enumerate() {
-            println!("Case {}: {}", i, t.name);
-            let (required, optional) =
-                filter_duplicates(to_utxo_vec(t.required), to_utxo_vec(t.optional));
-            assert_eq!(
-                required,
-                to_utxo_vec(t.exp_required),
-                "[{}:{}] unexpected `required` result",
-                i,
-                t.name
-            );
-            assert_eq!(
-                optional,
-                to_utxo_vec(t.exp_optional),
-                "[{}:{}] unexpected `optional` result",
-                i,
-                t.name
-            );
-        }
-    }
-}
-
-
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/error.rs.html deleted file mode 100644 index e0cfdb40bc..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/error.rs.html +++ /dev/null @@ -1,585 +0,0 @@ -error.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
-
// 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.
-
-//! Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
-
-use crate::descriptor::policy::PolicyError;
-use crate::descriptor::DescriptorError;
-use crate::wallet::coin_selection;
-use crate::{descriptor, KeychainKind};
-use alloc::string::String;
-use bitcoin::{absolute, psbt, OutPoint, Sequence, Txid};
-use core::fmt;
-
-/// Errors returned by miniscript when updating inconsistent PSBTs
-#[derive(Debug, Clone)]
-pub enum MiniscriptPsbtError {
-    /// Descriptor key conversion error
-    Conversion(miniscript::descriptor::ConversionError),
-    /// Return error type for PsbtExt::update_input_with_descriptor
-    UtxoUpdate(miniscript::psbt::UtxoUpdateError),
-    /// Return error type for PsbtExt::update_output_with_descriptor
-    OutputUpdate(miniscript::psbt::OutputUpdateError),
-}
-
-impl fmt::Display for MiniscriptPsbtError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::Conversion(err) => write!(f, "Conversion error: {}", err),
-            Self::UtxoUpdate(err) => write!(f, "UTXO update error: {}", err),
-            Self::OutputUpdate(err) => write!(f, "Output update error: {}", err),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for MiniscriptPsbtError {}
-
-#[derive(Debug)]
-/// Error returned from [`TxBuilder::finish`]
-///
-/// [`TxBuilder::finish`]: crate::wallet::tx_builder::TxBuilder::finish
-pub enum CreateTxError {
-    /// There was a problem with the descriptors passed in
-    Descriptor(DescriptorError),
-    /// We were unable to load wallet data from or write wallet data to the persistence backend
-    Persist(anyhow::Error),
-    /// There was a problem while extracting and manipulating policies
-    Policy(PolicyError),
-    /// Spending policy is not compatible with this [`KeychainKind`]
-    SpendingPolicyRequired(KeychainKind),
-    /// Requested invalid transaction version '0'
-    Version0,
-    /// Requested transaction version `1`, but at least `2` is needed to use OP_CSV
-    Version1Csv,
-    /// Requested `LockTime` is less than is required to spend from this script
-    LockTime {
-        /// Requested `LockTime`
-        requested: absolute::LockTime,
-        /// Required `LockTime`
-        required: absolute::LockTime,
-    },
-    /// Cannot enable RBF with a `Sequence` >= 0xFFFFFFFE
-    RbfSequence,
-    /// Cannot enable RBF with `Sequence` given a required OP_CSV
-    RbfSequenceCsv {
-        /// Given RBF `Sequence`
-        rbf: Sequence,
-        /// Required OP_CSV `Sequence`
-        csv: Sequence,
-    },
-    /// When bumping a tx the absolute fee requested is lower than replaced tx absolute fee
-    FeeTooLow {
-        /// Required fee absolute value (satoshi)
-        required: u64,
-    },
-    /// When bumping a tx the fee rate requested is lower than required
-    FeeRateTooLow {
-        /// Required fee rate
-        required: bitcoin::FeeRate,
-    },
-    /// `manually_selected_only` option is selected but no utxo has been passed
-    NoUtxosSelected,
-    /// Output created is under the dust limit, 546 satoshis
-    OutputBelowDustLimit(usize),
-    /// The `change_policy` was set but the wallet does not have a change_descriptor
-    ChangePolicyDescriptor,
-    /// There was an error with coin selection
-    CoinSelection(coin_selection::Error),
-    /// Wallet's UTXO set is not enough to cover recipient's requested plus fee
-    InsufficientFunds {
-        /// Sats needed for some transaction
-        needed: u64,
-        /// Sats available for spending
-        available: u64,
-    },
-    /// Cannot build a tx without recipients
-    NoRecipients,
-    /// Partially signed bitcoin transaction error
-    Psbt(psbt::Error),
-    /// In order to use the [`TxBuilder::add_global_xpubs`] option every extended
-    /// key in the descriptor must either be a master key itself (having depth = 0) or have an
-    /// explicit origin provided
-    ///
-    /// [`TxBuilder::add_global_xpubs`]: crate::wallet::tx_builder::TxBuilder::add_global_xpubs
-    MissingKeyOrigin(String),
-    /// Happens when trying to spend an UTXO that is not in the internal database
-    UnknownUtxo,
-    /// Missing non_witness_utxo on foreign utxo for given `OutPoint`
-    MissingNonWitnessUtxo(OutPoint),
-    /// Miniscript PSBT error
-    MiniscriptPsbt(MiniscriptPsbtError),
-}
-
-impl fmt::Display for CreateTxError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::Descriptor(e) => e.fmt(f),
-            Self::Persist(e) => {
-                write!(
-                    f,
-                    "failed to load wallet data from or write wallet data to persistence backend: {}",
-                    e
-                )
-            }
-            Self::Policy(e) => e.fmt(f),
-            CreateTxError::SpendingPolicyRequired(keychain_kind) => {
-                write!(f, "Spending policy required: {:?}", keychain_kind)
-            }
-            CreateTxError::Version0 => {
-                write!(f, "Invalid version `0`")
-            }
-            CreateTxError::Version1Csv => {
-                write!(
-                    f,
-                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
-                )
-            }
-            CreateTxError::LockTime {
-                requested,
-                required,
-            } => {
-                write!(f, "TxBuilder requested timelock of `{:?}`, but at least `{:?}` is required to spend from this script", required, requested)
-            }
-            CreateTxError::RbfSequence => {
-                write!(f, "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")
-            }
-            CreateTxError::RbfSequenceCsv { rbf, csv } => {
-                write!(
-                    f,
-                    "Cannot enable RBF with nSequence `{:?}` given a required OP_CSV of `{:?}`",
-                    rbf, csv
-                )
-            }
-            CreateTxError::FeeTooLow { required } => {
-                write!(f, "Fee to low: required {} sat", required)
-            }
-            CreateTxError::FeeRateTooLow { required } => {
-                write!(
-                    f,
-                    // Note: alternate fmt as sat/vb (ceil) available in bitcoin-0.31
-                    //"Fee rate too low: required {required:#}"
-                    "Fee rate too low: required {} sat/vb",
-                    crate::floating_rate!(required)
-                )
-            }
-            CreateTxError::NoUtxosSelected => {
-                write!(f, "No UTXO selected")
-            }
-            CreateTxError::OutputBelowDustLimit(limit) => {
-                write!(f, "Output below the dust limit: {}", limit)
-            }
-            CreateTxError::ChangePolicyDescriptor => {
-                write!(
-                    f,
-                    "The `change_policy` can be set only if the wallet has a change_descriptor"
-                )
-            }
-            CreateTxError::CoinSelection(e) => e.fmt(f),
-            CreateTxError::InsufficientFunds { needed, available } => {
-                write!(
-                    f,
-                    "Insufficient funds: {} sat available of {} sat needed",
-                    available, needed
-                )
-            }
-            CreateTxError::NoRecipients => {
-                write!(f, "Cannot build tx without recipients")
-            }
-            CreateTxError::Psbt(e) => e.fmt(f),
-            CreateTxError::MissingKeyOrigin(err) => {
-                write!(f, "Missing key origin: {}", err)
-            }
-            CreateTxError::UnknownUtxo => {
-                write!(f, "UTXO not found in the internal database")
-            }
-            CreateTxError::MissingNonWitnessUtxo(outpoint) => {
-                write!(f, "Missing non_witness_utxo on foreign utxo {}", outpoint)
-            }
-            CreateTxError::MiniscriptPsbt(err) => {
-                write!(f, "Miniscript PSBT error: {}", err)
-            }
-        }
-    }
-}
-
-impl From<descriptor::error::Error> for CreateTxError {
-    fn from(err: descriptor::error::Error) -> Self {
-        CreateTxError::Descriptor(err)
-    }
-}
-
-impl From<PolicyError> for CreateTxError {
-    fn from(err: PolicyError) -> Self {
-        CreateTxError::Policy(err)
-    }
-}
-
-impl From<MiniscriptPsbtError> for CreateTxError {
-    fn from(err: MiniscriptPsbtError) -> Self {
-        CreateTxError::MiniscriptPsbt(err)
-    }
-}
-
-impl From<psbt::Error> for CreateTxError {
-    fn from(err: psbt::Error) -> Self {
-        CreateTxError::Psbt(err)
-    }
-}
-
-impl From<coin_selection::Error> for CreateTxError {
-    fn from(err: coin_selection::Error) -> Self {
-        CreateTxError::CoinSelection(err)
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for CreateTxError {}
-
-#[derive(Debug)]
-/// Error returned from [`Wallet::build_fee_bump`]
-///
-/// [`Wallet::build_fee_bump`]: super::Wallet::build_fee_bump
-pub enum BuildFeeBumpError {
-    /// Happens when trying to spend an UTXO that is not in the internal database
-    UnknownUtxo(OutPoint),
-    /// Thrown when a tx is not found in the internal database
-    TransactionNotFound(Txid),
-    /// Happens when trying to bump a transaction that is already confirmed
-    TransactionConfirmed(Txid),
-    /// Trying to replace a tx that has a sequence >= `0xFFFFFFFE`
-    IrreplaceableTransaction(Txid),
-    /// Node doesn't have data to estimate a fee rate
-    FeeRateUnavailable,
-}
-
-impl fmt::Display for BuildFeeBumpError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::UnknownUtxo(outpoint) => write!(
-                f,
-                "UTXO not found in the internal database with txid: {}, vout: {}",
-                outpoint.txid, outpoint.vout
-            ),
-            Self::TransactionNotFound(txid) => {
-                write!(
-                    f,
-                    "Transaction not found in the internal database with txid: {}",
-                    txid
-                )
-            }
-            Self::TransactionConfirmed(txid) => {
-                write!(f, "Transaction already confirmed with txid: {}", txid)
-            }
-            Self::IrreplaceableTransaction(txid) => {
-                write!(f, "Transaction can't be replaced with txid: {}", txid)
-            }
-            Self::FeeRateUnavailable => write!(f, "Fee rate unavailable"),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for BuildFeeBumpError {}
-
-
\ No newline at end of file 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 deleted file mode 100644 index 38000bb368..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/export.rs.html +++ /dev/null @@ -1,685 +0,0 @@ -export.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
-
// 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.
-
-//! Wallet export
-//!
-//! This modules implements the wallet export format used by [FullyNoded](https://github.com/Fonta1n3/FullyNoded/blob/10b7808c8b929b171cca537fb50522d015168ac9/Docs/Wallets/Wallet-Export-Spec.md).
-//!
-//! ## Examples
-//!
-//! ### Import from JSON
-//!
-//! ```
-//! # use std::str::FromStr;
-//! # use bitcoin::*;
-//! # use bdk::wallet::export::*;
-//! # use bdk::*;
-//! let import = r#"{
-//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
-//!     "blockheight":1782088,
-//!     "label":"testnet"
-//! }"#;
-//!
-//! let import = FullyNodedExport::from_str(import)?;
-//! let wallet = Wallet::new_no_persist(
-//!     &import.descriptor(),
-//!     import.change_descriptor().as_ref(),
-//!     Network::Testnet,
-//! )?;
-//! # Ok::<_, Box<dyn std::error::Error>>(())
-//! ```
-//!
-//! ### Export a `Wallet`
-//! ```
-//! # use bitcoin::*;
-//! # use bdk::wallet::export::*;
-//! # use bdk::*;
-//! let wallet = Wallet::new_no_persist(
-//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
-//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
-//!     Network::Testnet,
-//! )?;
-//! let export = FullyNodedExport::export_wallet(&wallet, "exported wallet", true).unwrap();
-//!
-//! println!("Exported: {}", export.to_string());
-//! # Ok::<_, Box<dyn std::error::Error>>(())
-//! ```
-
-use alloc::string::String;
-use core::fmt;
-use core::str::FromStr;
-use serde::{Deserialize, Serialize};
-
-use miniscript::descriptor::{ShInner, WshInner};
-use miniscript::{Descriptor, ScriptContext, Terminal};
-
-use crate::types::KeychainKind;
-use crate::wallet::Wallet;
-
-/// Alias for [`FullyNodedExport`]
-#[deprecated(since = "0.18.0", note = "Please use [`FullyNodedExport`] instead")]
-pub type WalletExport = FullyNodedExport;
-
-/// Structure that contains the export of a wallet
-///
-/// For a usage example see [this module](crate::wallet::export)'s documentation.
-#[derive(Debug, Serialize, Deserialize)]
-pub struct FullyNodedExport {
-    descriptor: String,
-    /// Earliest block to rescan when looking for the wallet's transactions
-    pub blockheight: u32,
-    /// Arbitrary label for the wallet
-    pub label: String,
-}
-
-impl fmt::Display for FullyNodedExport {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", serde_json::to_string(self).unwrap())
-    }
-}
-
-impl FromStr for FullyNodedExport {
-    type Err = serde_json::Error;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        serde_json::from_str(s)
-    }
-}
-
-fn remove_checksum(s: String) -> String {
-    s.split_once('#').map(|(a, _)| String::from(a)).unwrap()
-}
-
-impl FullyNodedExport {
-    /// 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.
-    ///
-    /// If `include_blockheight` is `true`, this function will look into the `wallet`'s database
-    /// 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`.
-    pub fn export_wallet(
-        wallet: &Wallet,
-        label: &str,
-        include_blockheight: bool,
-    ) -> Result<Self, &'static str> {
-        let descriptor = wallet
-            .get_descriptor_for_keychain(KeychainKind::External)
-            .to_string_with_secret(
-                &wallet
-                    .get_signers(KeychainKind::External)
-                    .as_key_map(wallet.secp_ctx()),
-            );
-        let descriptor = remove_checksum(descriptor);
-        Self::is_compatible_with_core(&descriptor)?;
-
-        let blockheight = if include_blockheight {
-            wallet.transactions().next().map_or(0, |canonical_tx| {
-                match canonical_tx.chain_position {
-                    bdk_chain::ChainPosition::Confirmed(a) => a.confirmation_height,
-                    bdk_chain::ChainPosition::Unconfirmed(_) => 0,
-                }
-            })
-        } else {
-            0
-        };
-
-        let export = FullyNodedExport {
-            descriptor,
-            label: label.into(),
-            blockheight,
-        };
-
-        let change_descriptor = match wallet.public_descriptor(KeychainKind::Internal).is_some() {
-            false => None,
-            true => {
-                let descriptor = wallet
-                    .get_descriptor_for_keychain(KeychainKind::Internal)
-                    .to_string_with_secret(
-                        &wallet
-                            .get_signers(KeychainKind::Internal)
-                            .as_key_map(wallet.secp_ctx()),
-                    );
-                Some(remove_checksum(descriptor))
-            }
-        };
-        if export.change_descriptor() != change_descriptor {
-            return Err("Incompatible change descriptor");
-        }
-
-        Ok(export)
-    }
-
-    fn is_compatible_with_core(descriptor: &str) -> Result<(), &'static str> {
-        fn check_ms<Ctx: ScriptContext>(
-            terminal: &Terminal<String, Ctx>,
-        ) -> Result<(), &'static str> {
-            if let Terminal::Multi(_, _) = terminal {
-                Ok(())
-            } else {
-                Err("The descriptor contains operators not supported by Bitcoin Core")
-            }
-        }
-
-        // pkh(), wpkh(), sh(wpkh()) are always fine, as well as multi() and sortedmulti()
-        match Descriptor::<String>::from_str(descriptor).map_err(|_| "Invalid descriptor")? {
-            Descriptor::Pkh(_) | Descriptor::Wpkh(_) => Ok(()),
-            Descriptor::Sh(sh) => match sh.as_inner() {
-                ShInner::Wpkh(_) => Ok(()),
-                ShInner::SortedMulti(_) => Ok(()),
-                ShInner::Wsh(wsh) => match wsh.as_inner() {
-                    WshInner::SortedMulti(_) => Ok(()),
-                    WshInner::Ms(ms) => check_ms(&ms.node),
-                },
-                ShInner::Ms(ms) => check_ms(&ms.node),
-            },
-            Descriptor::Wsh(wsh) => match wsh.as_inner() {
-                WshInner::SortedMulti(_) => Ok(()),
-                WshInner::Ms(ms) => check_ms(&ms.node),
-            },
-            _ => Err("The descriptor is not compatible with Bitcoin Core"),
-        }
-    }
-
-    /// Return the external descriptor
-    pub fn descriptor(&self) -> String {
-        self.descriptor.clone()
-    }
-
-    /// Return the internal descriptor, if present
-    pub fn change_descriptor(&self) -> Option<String> {
-        let replaced = self.descriptor.replace("/0/*", "/1/*");
-
-        if replaced != self.descriptor {
-            Some(replaced)
-        } else {
-            None
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use core::str::FromStr;
-
-    use crate::std::string::ToString;
-    use bdk_chain::{BlockId, ConfirmationTime};
-    use bitcoin::hashes::Hash;
-    use bitcoin::{transaction, BlockHash, Network, Transaction};
-
-    use super::*;
-    use crate::wallet::Wallet;
-
-    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: transaction::Version::non_standard(0),
-            lock_time: bitcoin::absolute::LockTime::ZERO,
-        };
-        wallet
-            .insert_checkpoint(BlockId {
-                height: 5001,
-                hash: BlockHash::all_zeros(),
-            })
-            .unwrap();
-        wallet
-            .insert_tx(
-                transaction,
-                ConfirmationTime::Confirmed {
-                    height: 5000,
-                    time: 0,
-                },
-            )
-            .unwrap();
-        wallet
-    }
-
-    #[test]
-    fn test_export_bip44() {
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
-
-        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);
-        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
-        assert_eq!(export.blockheight, 5000);
-        assert_eq!(export.label, "Test Label");
-    }
-
-    #[test]
-    #[should_panic(expected = "Incompatible change descriptor")]
-    fn test_export_no_change() {
-        // This wallet explicitly doesn't have a change descriptor. It should be impossible to
-        // export, because exporting this kind of external descriptor normally implies the
-        // existence of an internal descriptor
-
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-
-        let wallet = get_test_wallet(descriptor, None, Network::Bitcoin);
-        FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "Incompatible change descriptor")]
-    fn test_export_incompatible_change() {
-        // This wallet has a change descriptor, but the derivation path is not in the "standard"
-        // bip44/49/etc format
-
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/50'/0'/1/*)";
-
-        let wallet = get_test_wallet(descriptor, Some(change_descriptor), Network::Bitcoin);
-        FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
-    }
-
-    #[test]
-    fn test_export_multi() {
-        let descriptor = "wsh(multi(2,\
-                                [73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*,\
-                                [f9f62194/48'/0'/0'/2']tpubDDp3ZSH1yCwusRppH7zgSxq2t1VEUyXSeEp8E5aFS8m43MknUjiF1bSLo3CGWAxbDyhF1XowA5ukPzyJZjznYk3kYi6oe7QxtX2euvKWsk4/0/*,\
-                                [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/0/*\
-                          ))";
-        let change_descriptor = "wsh(multi(2,\
-                                       [73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/1/*,\
-                                       [f9f62194/48'/0'/0'/2']tpubDDp3ZSH1yCwusRppH7zgSxq2t1VEUyXSeEp8E5aFS8m43MknUjiF1bSLo3CGWAxbDyhF1XowA5ukPzyJZjznYk3kYi6oe7QxtX2euvKWsk4/1/*,\
-                                       [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/1/*\
-                                 ))";
-
-        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);
-        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
-        assert_eq!(export.blockheight, 5000);
-        assert_eq!(export.label, "Test Label");
-    }
-
-    #[test]
-    fn test_export_to_json() {
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
-
-        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\"}");
-    }
-
-    #[test]
-    fn test_export_from_json() {
-        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
-        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
-
-        let import_str = "{\"descriptor\":\"wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44\'/0\'/0\'/0/*)\",\"blockheight\":5000,\"label\":\"Test Label\"}";
-        let export = FullyNodedExport::from_str(import_str).unwrap();
-
-        assert_eq!(export.descriptor(), descriptor);
-        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
-        assert_eq!(export.blockheight, 5000);
-        assert_eq!(export.label, "Test Label");
-    }
-}
-
-
\ 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 deleted file mode 100644 index 7099f3cf37..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/mod.rs.html +++ /dev/null @@ -1,5419 +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
-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
-1148
-1149
-1150
-1151
-1152
-1153
-1154
-1155
-1156
-1157
-1158
-1159
-1160
-1161
-1162
-1163
-1164
-1165
-1166
-1167
-1168
-1169
-1170
-1171
-1172
-1173
-1174
-1175
-1176
-1177
-1178
-1179
-1180
-1181
-1182
-1183
-1184
-1185
-1186
-1187
-1188
-1189
-1190
-1191
-1192
-1193
-1194
-1195
-1196
-1197
-1198
-1199
-1200
-1201
-1202
-1203
-1204
-1205
-1206
-1207
-1208
-1209
-1210
-1211
-1212
-1213
-1214
-1215
-1216
-1217
-1218
-1219
-1220
-1221
-1222
-1223
-1224
-1225
-1226
-1227
-1228
-1229
-1230
-1231
-1232
-1233
-1234
-1235
-1236
-1237
-1238
-1239
-1240
-1241
-1242
-1243
-1244
-1245
-1246
-1247
-1248
-1249
-1250
-1251
-1252
-1253
-1254
-1255
-1256
-1257
-1258
-1259
-1260
-1261
-1262
-1263
-1264
-1265
-1266
-1267
-1268
-1269
-1270
-1271
-1272
-1273
-1274
-1275
-1276
-1277
-1278
-1279
-1280
-1281
-1282
-1283
-1284
-1285
-1286
-1287
-1288
-1289
-1290
-1291
-1292
-1293
-1294
-1295
-1296
-1297
-1298
-1299
-1300
-1301
-1302
-1303
-1304
-1305
-1306
-1307
-1308
-1309
-1310
-1311
-1312
-1313
-1314
-1315
-1316
-1317
-1318
-1319
-1320
-1321
-1322
-1323
-1324
-1325
-1326
-1327
-1328
-1329
-1330
-1331
-1332
-1333
-1334
-1335
-1336
-1337
-1338
-1339
-1340
-1341
-1342
-1343
-1344
-1345
-1346
-1347
-1348
-1349
-1350
-1351
-1352
-1353
-1354
-1355
-1356
-1357
-1358
-1359
-1360
-1361
-1362
-1363
-1364
-1365
-1366
-1367
-1368
-1369
-1370
-1371
-1372
-1373
-1374
-1375
-1376
-1377
-1378
-1379
-1380
-1381
-1382
-1383
-1384
-1385
-1386
-1387
-1388
-1389
-1390
-1391
-1392
-1393
-1394
-1395
-1396
-1397
-1398
-1399
-1400
-1401
-1402
-1403
-1404
-1405
-1406
-1407
-1408
-1409
-1410
-1411
-1412
-1413
-1414
-1415
-1416
-1417
-1418
-1419
-1420
-1421
-1422
-1423
-1424
-1425
-1426
-1427
-1428
-1429
-1430
-1431
-1432
-1433
-1434
-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
-1596
-1597
-1598
-1599
-1600
-1601
-1602
-1603
-1604
-1605
-1606
-1607
-1608
-1609
-1610
-1611
-1612
-1613
-1614
-1615
-1616
-1617
-1618
-1619
-1620
-1621
-1622
-1623
-1624
-1625
-1626
-1627
-1628
-1629
-1630
-1631
-1632
-1633
-1634
-1635
-1636
-1637
-1638
-1639
-1640
-1641
-1642
-1643
-1644
-1645
-1646
-1647
-1648
-1649
-1650
-1651
-1652
-1653
-1654
-1655
-1656
-1657
-1658
-1659
-1660
-1661
-1662
-1663
-1664
-1665
-1666
-1667
-1668
-1669
-1670
-1671
-1672
-1673
-1674
-1675
-1676
-1677
-1678
-1679
-1680
-1681
-1682
-1683
-1684
-1685
-1686
-1687
-1688
-1689
-1690
-1691
-1692
-1693
-1694
-1695
-1696
-1697
-1698
-1699
-1700
-1701
-1702
-1703
-1704
-1705
-1706
-1707
-1708
-1709
-1710
-1711
-1712
-1713
-1714
-1715
-1716
-1717
-1718
-1719
-1720
-1721
-1722
-1723
-1724
-1725
-1726
-1727
-1728
-1729
-1730
-1731
-1732
-1733
-1734
-1735
-1736
-1737
-1738
-1739
-1740
-1741
-1742
-1743
-1744
-1745
-1746
-1747
-1748
-1749
-1750
-1751
-1752
-1753
-1754
-1755
-1756
-1757
-1758
-1759
-1760
-1761
-1762
-1763
-1764
-1765
-1766
-1767
-1768
-1769
-1770
-1771
-1772
-1773
-1774
-1775
-1776
-1777
-1778
-1779
-1780
-1781
-1782
-1783
-1784
-1785
-1786
-1787
-1788
-1789
-1790
-1791
-1792
-1793
-1794
-1795
-1796
-1797
-1798
-1799
-1800
-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
-
// 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.
-
-//! Wallet
-//!
-//! This module defines the [`Wallet`].
-use crate::collections::{BTreeMap, HashMap};
-use alloc::{
-    boxed::Box,
-    string::{String, ToString},
-    sync::Arc,
-    vec::Vec,
-};
-pub use bdk_chain::keychain::Balance;
-use bdk_chain::{
-    indexed_tx_graph,
-    keychain::{self, KeychainTxOutIndex},
-    local_chain::{
-        self, ApplyHeaderError, CannotConnectError, CheckPoint, CheckPointIter, LocalChain,
-    },
-    spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult},
-    tx_graph::{CanonicalTx, TxGraph},
-    Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeHeightAnchor, FullTxOut,
-    IndexedTxGraph,
-};
-use bdk_persist::{Persist, PersistBackend};
-use bitcoin::secp256k1::{All, Secp256k1};
-use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
-use bitcoin::{
-    absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence,
-    Transaction, TxOut, Txid, Witness,
-};
-use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt};
-use bitcoin::{constants::genesis_block, Amount};
-use core::fmt;
-use core::ops::Deref;
-use descriptor::error::Error as DescriptorError;
-use miniscript::psbt::{PsbtExt, PsbtInputExt, PsbtInputSatisfier};
-
-use bdk_chain::tx_graph::CalculateFeeError;
-
-pub mod coin_selection;
-pub mod export;
-pub mod signer;
-pub mod tx_builder;
-pub(crate) mod utils;
-
-pub mod error;
-
-pub use utils::IsDust;
-
-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::descriptor::policy::BuildSatisfaction;
-use crate::descriptor::{
-    self, calc_checksum, into_wallet_descriptor_checked, DerivedDescriptor, DescriptorMeta,
-    ExtendedDescriptor, ExtractPolicy, IntoWalletDescriptor, Policy, XKeyUtils,
-};
-use crate::psbt::PsbtUtils;
-use crate::signer::SignerError;
-use crate::types::*;
-use crate::wallet::coin_selection::Excess::{Change, NoChange};
-use crate::wallet::error::{BuildFeeBumpError, CreateTxError, MiniscriptPsbtError};
-
-const COINBASE_MATURITY: u32 = 100;
-
-/// A Bitcoin wallet
-///
-/// The `Wallet` 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. [`signer`]s that can contribute signatures to addresses instantiated from the descriptors.
-///
-/// [`signer`]: crate::signer
-#[derive(Debug)]
-pub struct Wallet {
-    signers: Arc<SignersContainer>,
-    change_signers: Arc<SignersContainer>,
-    chain: LocalChain,
-    indexed_graph: IndexedTxGraph<ConfirmationTimeHeightAnchor, KeychainTxOutIndex<KeychainKind>>,
-    persist: Persist<ChangeSet>,
-    network: Network,
-    secp: SecpCtx,
-}
-
-/// An update to [`Wallet`].
-///
-/// It updates [`bdk_chain::keychain::KeychainTxOutIndex`], [`bdk_chain::TxGraph`] and [`local_chain::LocalChain`] atomically.
-#[derive(Debug, Clone, Default)]
-pub struct Update {
-    /// Contains the last active derivation indices per keychain (`K`), which is used to update the
-    /// [`KeychainTxOutIndex`].
-    pub last_active_indices: BTreeMap<KeychainKind, u32>,
-
-    /// Update for the wallet's internal [`TxGraph`].
-    pub graph: TxGraph<ConfirmationTimeHeightAnchor>,
-
-    /// Update for the wallet's internal [`LocalChain`].
-    ///
-    /// [`LocalChain`]: local_chain::LocalChain
-    pub chain: Option<CheckPoint>,
-}
-
-impl From<FullScanResult<KeychainKind>> for Update {
-    fn from(value: FullScanResult<KeychainKind>) -> Self {
-        Self {
-            last_active_indices: value.last_active_indices,
-            graph: value.graph_update,
-            chain: Some(value.chain_update),
-        }
-    }
-}
-
-impl From<SyncResult> for Update {
-    fn from(value: SyncResult) -> Self {
-        Self {
-            last_active_indices: BTreeMap::new(),
-            graph: value.graph_update,
-            chain: Some(value.chain_update),
-        }
-    }
-}
-
-/// The changes made to a wallet by applying an [`Update`].
-#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)]
-pub struct ChangeSet {
-    /// Changes to the [`LocalChain`].
-    ///
-    /// [`LocalChain`]: local_chain::LocalChain
-    pub chain: local_chain::ChangeSet,
-
-    /// Changes to [`IndexedTxGraph`].
-    ///
-    /// [`IndexedTxGraph`]: bdk_chain::indexed_tx_graph::IndexedTxGraph
-    pub indexed_tx_graph: indexed_tx_graph::ChangeSet<
-        ConfirmationTimeHeightAnchor,
-        keychain::ChangeSet<KeychainKind>,
-    >,
-
-    /// Stores the network type of the wallet.
-    pub network: Option<Network>,
-}
-
-impl Append for ChangeSet {
-    fn append(&mut self, other: Self) {
-        Append::append(&mut self.chain, other.chain);
-        Append::append(&mut self.indexed_tx_graph, other.indexed_tx_graph);
-        if other.network.is_some() {
-            debug_assert!(
-                self.network.is_none() || self.network == other.network,
-                "network type must be consistent"
-            );
-            self.network = other.network;
-        }
-    }
-
-    fn is_empty(&self) -> bool {
-        self.chain.is_empty() && self.indexed_tx_graph.is_empty()
-    }
-}
-
-impl From<local_chain::ChangeSet> for ChangeSet {
-    fn from(chain: local_chain::ChangeSet) -> Self {
-        Self {
-            chain,
-            ..Default::default()
-        }
-    }
-}
-
-impl
-    From<
-        indexed_tx_graph::ChangeSet<
-            ConfirmationTimeHeightAnchor,
-            keychain::ChangeSet<KeychainKind>,
-        >,
-    > for ChangeSet
-{
-    fn from(
-        indexed_tx_graph: indexed_tx_graph::ChangeSet<
-            ConfirmationTimeHeightAnchor,
-            keychain::ChangeSet<KeychainKind>,
-        >,
-    ) -> Self {
-        Self {
-            indexed_tx_graph,
-            ..Default::default()
-        }
-    }
-}
-
-/// A derived address and the index it was found at.
-/// For convenience this automatically derefs to `Address`
-#[derive(Debug, PartialEq, Eq)]
-pub struct AddressInfo {
-    /// Child index of this address
-    pub index: u32,
-    /// Address
-    pub address: Address,
-    /// Type of keychain
-    pub keychain: KeychainKind,
-}
-
-impl Deref for AddressInfo {
-    type Target = Address;
-
-    fn deref(&self) -> &Self::Target {
-        &self.address
-    }
-}
-
-impl fmt::Display for AddressInfo {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.address)
-    }
-}
-
-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, DescriptorError> {
-        Self::new(descriptor, change_descriptor, (), network).map_err(|e| match e {
-            NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"),
-            NewError::Descriptor(e) => e,
-            NewError::Persist(_) => unreachable!("mock-write must always succeed"),
-        })
-    }
-
-    /// Creates a wallet that does not persist data, with a custom genesis hash.
-    pub fn new_no_persist_with_genesis_hash<E: IntoWalletDescriptor>(
-        descriptor: E,
-        change_descriptor: Option<E>,
-        network: Network,
-        genesis_hash: BlockHash,
-    ) -> Result<Self, crate::descriptor::DescriptorError> {
-        Self::new_with_genesis_hash(descriptor, change_descriptor, (), network, genesis_hash)
-            .map_err(|e| match e {
-                NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"),
-                NewError::Descriptor(e) => e,
-                NewError::Persist(_) => unreachable!("mock-write must always succeed"),
-            })
-    }
-}
-
-/// The error type when constructing a fresh [`Wallet`].
-///
-/// Methods [`new`] and [`new_with_genesis_hash`] may return this error.
-///
-/// [`new`]: Wallet::new
-/// [`new_with_genesis_hash`]: Wallet::new_with_genesis_hash
-#[derive(Debug)]
-pub enum NewError {
-    /// Database already has data.
-    NonEmptyDatabase,
-    /// There was problem with the passed-in descriptor(s).
-    Descriptor(crate::descriptor::DescriptorError),
-    /// We were unable to write the wallet's data to the persistence backend.
-    Persist(anyhow::Error),
-}
-
-impl fmt::Display for NewError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            NewError::NonEmptyDatabase => write!(
-                f,
-                "database already has data - use `load` or `new_or_load` methods instead"
-            ),
-            NewError::Descriptor(e) => e.fmt(f),
-            NewError::Persist(e) => e.fmt(f),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for NewError {}
-
-/// The error type when loading a [`Wallet`] from persistence.
-///
-/// Method [`load`] may return this error.
-///
-/// [`load`]: Wallet::load
-#[derive(Debug)]
-pub enum LoadError {
-    /// There was a problem with the passed-in descriptor(s).
-    Descriptor(crate::descriptor::DescriptorError),
-    /// Loading data from the persistence backend failed.
-    Persist(anyhow::Error),
-    /// Wallet not initialized, persistence backend is empty.
-    NotInitialized,
-    /// Data loaded from persistence is missing network type.
-    MissingNetwork,
-    /// Data loaded from persistence is missing genesis hash.
-    MissingGenesis,
-    /// Data loaded from persistence is missing descriptor.
-    MissingDescriptor,
-}
-
-impl fmt::Display for LoadError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            LoadError::Descriptor(e) => e.fmt(f),
-            LoadError::Persist(e) => e.fmt(f),
-            LoadError::NotInitialized => {
-                write!(f, "wallet is not initialized, persistence backend is empty")
-            }
-            LoadError::MissingNetwork => write!(f, "loaded data is missing network type"),
-            LoadError::MissingGenesis => write!(f, "loaded data is missing genesis hash"),
-            LoadError::MissingDescriptor => write!(f, "loaded data is missing descriptor"),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for LoadError {}
-
-/// Error type for when we try load a [`Wallet`] from persistence and creating it if non-existent.
-///
-/// Methods [`new_or_load`] and [`new_or_load_with_genesis_hash`] may return this error.
-///
-/// [`new_or_load`]: Wallet::new_or_load
-/// [`new_or_load_with_genesis_hash`]: Wallet::new_or_load_with_genesis_hash
-#[derive(Debug)]
-pub enum NewOrLoadError {
-    /// There is a problem with the passed-in descriptor.
-    Descriptor(crate::descriptor::DescriptorError),
-    /// Either writing to or loading from the persistence backend failed.
-    Persist(anyhow::Error),
-    /// Wallet is not initialized, persistence backend is empty.
-    NotInitialized,
-    /// The loaded genesis hash does not match what was provided.
-    LoadedGenesisDoesNotMatch {
-        /// The expected genesis block hash.
-        expected: BlockHash,
-        /// The block hash loaded from persistence.
-        got: Option<BlockHash>,
-    },
-    /// The loaded network type does not match what was provided.
-    LoadedNetworkDoesNotMatch {
-        /// The expected network type.
-        expected: Network,
-        /// The network type loaded from persistence.
-        got: Option<Network>,
-    },
-    /// The loaded desccriptor does not match what was provided.
-    LoadedDescriptorDoesNotMatch {
-        /// The descriptor loaded from persistence.
-        got: Option<ExtendedDescriptor>,
-        /// The keychain of the descriptor not matching
-        keychain: KeychainKind,
-    },
-}
-
-impl fmt::Display for NewOrLoadError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            NewOrLoadError::Descriptor(e) => e.fmt(f),
-            NewOrLoadError::Persist(e) => write!(
-                f,
-                "failed to either write to or load from persistence, {}",
-                e
-            ),
-            NewOrLoadError::NotInitialized => {
-                write!(f, "wallet is not initialized, persistence backend is empty")
-            }
-            NewOrLoadError::LoadedGenesisDoesNotMatch { expected, got } => {
-                write!(f, "loaded genesis hash is not {}, got {:?}", expected, got)
-            }
-            NewOrLoadError::LoadedNetworkDoesNotMatch { expected, got } => {
-                write!(f, "loaded network type is not {}, got {:?}", expected, got)
-            }
-            NewOrLoadError::LoadedDescriptorDoesNotMatch { got, keychain } => {
-                write!(
-                    f,
-                    "loaded descriptor is different from what was provided, got {:?} for keychain {:?}",
-                    got, keychain
-                )
-            }
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for NewOrLoadError {}
-
-/// An error that may occur when inserting a transaction into [`Wallet`].
-#[derive(Debug)]
-pub enum InsertTxError {
-    /// The error variant that occurs when the caller attempts to insert a transaction with a
-    /// confirmation height that is greater than the internal chain tip.
-    ConfirmationHeightCannotBeGreaterThanTip {
-        /// The internal chain's tip height.
-        tip_height: u32,
-        /// The introduced transaction's confirmation height.
-        tx_height: u32,
-    },
-}
-
-impl fmt::Display for InsertTxError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            InsertTxError::ConfirmationHeightCannotBeGreaterThanTip {
-                tip_height,
-                tx_height,
-            } => {
-                write!(f, "cannot insert tx with confirmation height ({}) higher than internal tip height ({})", tx_height, tip_height)
-            }
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for InsertTxError {}
-
-/// An error that may occur when applying a block to [`Wallet`].
-#[derive(Debug)]
-pub enum ApplyBlockError {
-    /// Occurs when the update chain cannot connect with original chain.
-    CannotConnect(CannotConnectError),
-    /// Occurs when the `connected_to` hash does not match the hash derived from `block`.
-    UnexpectedConnectedToHash {
-        /// Block hash of `connected_to`.
-        connected_to_hash: BlockHash,
-        /// Expected block hash of `connected_to`, as derived from `block`.
-        expected_hash: BlockHash,
-    },
-}
-
-impl fmt::Display for ApplyBlockError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            ApplyBlockError::CannotConnect(err) => err.fmt(f),
-            ApplyBlockError::UnexpectedConnectedToHash {
-                expected_hash: block_hash,
-                connected_to_hash: checkpoint_hash,
-            } => write!(
-                f,
-                "`connected_to` hash {} differs from the expected hash {} (which is derived from `block`)",
-                checkpoint_hash, block_hash
-            ),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for ApplyBlockError {}
-
-impl Wallet {
-    /// Initialize an empty [`Wallet`].
-    pub fn new<E: IntoWalletDescriptor>(
-        descriptor: E,
-        change_descriptor: Option<E>,
-        db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
-        network: Network,
-    ) -> Result<Self, NewError> {
-        let genesis_hash = genesis_block(network).block_hash();
-        Self::new_with_genesis_hash(descriptor, change_descriptor, db, network, genesis_hash)
-    }
-
-    /// Initialize an empty [`Wallet`] with a custom genesis hash.
-    ///
-    /// This is like [`Wallet::new`] with an additional `genesis_hash` parameter. This is useful
-    /// for syncing from alternative networks.
-    pub fn new_with_genesis_hash<E: IntoWalletDescriptor>(
-        descriptor: E,
-        change_descriptor: Option<E>,
-        mut db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
-        network: Network,
-        genesis_hash: BlockHash,
-    ) -> Result<Self, NewError> {
-        if let Ok(changeset) = db.load_from_persistence() {
-            if changeset.is_some() {
-                return Err(NewError::NonEmptyDatabase);
-            }
-        }
-        let secp = Secp256k1::new();
-        let (chain, chain_changeset) = LocalChain::from_genesis_hash(genesis_hash);
-        let mut index = KeychainTxOutIndex::<KeychainKind>::default();
-
-        let (signers, change_signers) =
-            create_signers(&mut index, &secp, descriptor, change_descriptor, network)
-                .map_err(NewError::Descriptor)?;
-
-        let indexed_graph = IndexedTxGraph::new(index);
-
-        let mut persist = Persist::new(db);
-        persist.stage(ChangeSet {
-            chain: chain_changeset,
-            indexed_tx_graph: indexed_graph.initial_changeset(),
-            network: Some(network),
-        });
-        persist.commit().map_err(NewError::Persist)?;
-
-        Ok(Wallet {
-            signers,
-            change_signers,
-            network,
-            chain,
-            indexed_graph,
-            persist,
-            secp,
-        })
-    }
-
-    /// Load [`Wallet`] from the given persistence backend.
-    ///
-    /// Note that the descriptor secret keys are not persisted to the db; this means that after
-    /// calling this method the [`Wallet`] **won't** know the secret keys, and as such, won't be
-    /// able to sign transactions.
-    ///
-    /// If you wish to use the wallet to sign transactions, you need to add the secret keys
-    /// manually to the [`Wallet`]:
-    ///
-    /// ```rust,no_run
-    /// # use bdk::Wallet;
-    /// # use bdk::signer::{SignersContainer, SignerOrdering};
-    /// # use bdk::descriptor::Descriptor;
-    /// # use bitcoin::key::Secp256k1;
-    /// # use bdk::KeychainKind;
-    /// # use bdk_file_store::Store;
-    /// #
-    /// # fn main() -> Result<(), anyhow::Error> {
-    /// # let temp_dir = tempfile::tempdir().expect("must create tempdir");
-    /// # let file_path = temp_dir.path().join("store.db");
-    /// # let db: Store<bdk::wallet::ChangeSet> = Store::create_new(&[], &file_path).expect("must create db");
-    /// let secp = Secp256k1::new();
-    ///
-    /// let (external_descriptor, external_keymap) = Descriptor::parse_descriptor(&secp, "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)").unwrap();
-    /// let (internal_descriptor, internal_keymap) = Descriptor::parse_descriptor(&secp, "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)").unwrap();
-    ///
-    /// let external_signer_container = SignersContainer::build(external_keymap, &external_descriptor, &secp);
-    /// let internal_signer_container = SignersContainer::build(internal_keymap, &internal_descriptor, &secp);
-    ///
-    /// let mut wallet = Wallet::load(db)?;
-    ///
-    /// external_signer_container.signers().into_iter()
-    ///     .for_each(|s| wallet.add_signer(KeychainKind::External, SignerOrdering::default(), s.clone()));
-    /// internal_signer_container.signers().into_iter()
-    ///     .for_each(|s| wallet.add_signer(KeychainKind::Internal, SignerOrdering::default(), s.clone()));
-    /// # Ok(())
-    /// # }
-    /// ```
-    ///
-    /// Alternatively, you can call [`Wallet::new_or_load`], which will add the private keys of the
-    /// passed-in descriptors to the [`Wallet`].
-    pub fn load(
-        mut db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
-    ) -> Result<Self, LoadError> {
-        let changeset = db
-            .load_from_persistence()
-            .map_err(LoadError::Persist)?
-            .ok_or(LoadError::NotInitialized)?;
-        Self::load_from_changeset(db, changeset)
-    }
-
-    fn load_from_changeset(
-        db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
-        changeset: ChangeSet,
-    ) -> Result<Self, LoadError> {
-        let secp = Secp256k1::new();
-        let network = changeset.network.ok_or(LoadError::MissingNetwork)?;
-        let chain =
-            LocalChain::from_changeset(changeset.chain).map_err(|_| LoadError::MissingGenesis)?;
-        let mut index = KeychainTxOutIndex::<KeychainKind>::default();
-        let descriptor = changeset
-            .indexed_tx_graph
-            .indexer
-            .keychains_added
-            .get(&KeychainKind::External)
-            .ok_or(LoadError::MissingDescriptor)?
-            .clone();
-        let change_descriptor = changeset
-            .indexed_tx_graph
-            .indexer
-            .keychains_added
-            .get(&KeychainKind::Internal)
-            .cloned();
-
-        let (signers, change_signers) =
-            create_signers(&mut index, &secp, descriptor, change_descriptor, network)
-                .expect("Can't fail: we passed in valid descriptors, recovered from the changeset");
-
-        let mut indexed_graph = IndexedTxGraph::new(index);
-        indexed_graph.apply_changeset(changeset.indexed_tx_graph);
-
-        let persist = Persist::new(db);
-
-        Ok(Wallet {
-            signers,
-            change_signers,
-            chain,
-            indexed_graph,
-            persist,
-            network,
-            secp,
-        })
-    }
-
-    /// Either loads [`Wallet`] from persistence, or initializes it if it does not exist.
-    ///
-    /// This method will fail if the loaded [`Wallet`] has different parameters to those provided.
-    pub fn new_or_load<E: IntoWalletDescriptor>(
-        descriptor: E,
-        change_descriptor: Option<E>,
-        db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
-        network: Network,
-    ) -> Result<Self, NewOrLoadError> {
-        let genesis_hash = genesis_block(network).block_hash();
-        Self::new_or_load_with_genesis_hash(
-            descriptor,
-            change_descriptor,
-            db,
-            network,
-            genesis_hash,
-        )
-    }
-
-    /// Either loads [`Wallet`] from persistence, or initializes it if it does not exist, using the
-    /// provided descriptor, change descriptor, network, and custom genesis hash.
-    ///
-    /// This method will fail if the loaded [`Wallet`] has different parameters to those provided.
-    /// This is like [`Wallet::new_or_load`] with an additional `genesis_hash` parameter. This is
-    /// useful for syncing from alternative networks.
-    pub fn new_or_load_with_genesis_hash<E: IntoWalletDescriptor>(
-        descriptor: E,
-        change_descriptor: Option<E>,
-        mut db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
-        network: Network,
-        genesis_hash: BlockHash,
-    ) -> Result<Self, NewOrLoadError> {
-        let changeset = db
-            .load_from_persistence()
-            .map_err(NewOrLoadError::Persist)?;
-        match changeset {
-            Some(changeset) => {
-                let mut wallet = Self::load_from_changeset(db, changeset).map_err(|e| match e {
-                    LoadError::Descriptor(e) => NewOrLoadError::Descriptor(e),
-                    LoadError::Persist(e) => NewOrLoadError::Persist(e),
-                    LoadError::NotInitialized => NewOrLoadError::NotInitialized,
-                    LoadError::MissingNetwork => NewOrLoadError::LoadedNetworkDoesNotMatch {
-                        expected: network,
-                        got: None,
-                    },
-                    LoadError::MissingGenesis => NewOrLoadError::LoadedGenesisDoesNotMatch {
-                        expected: genesis_hash,
-                        got: None,
-                    },
-                    LoadError::MissingDescriptor => NewOrLoadError::LoadedDescriptorDoesNotMatch {
-                        got: None,
-                        keychain: KeychainKind::External,
-                    },
-                })?;
-                if wallet.network != network {
-                    return Err(NewOrLoadError::LoadedNetworkDoesNotMatch {
-                        expected: network,
-                        got: Some(wallet.network),
-                    });
-                }
-                if wallet.chain.genesis_hash() != genesis_hash {
-                    return Err(NewOrLoadError::LoadedGenesisDoesNotMatch {
-                        expected: genesis_hash,
-                        got: Some(wallet.chain.genesis_hash()),
-                    });
-                }
-
-                let (expected_descriptor, expected_descriptor_keymap) = descriptor
-                    .into_wallet_descriptor(&wallet.secp, network)
-                    .map_err(NewOrLoadError::Descriptor)?;
-                let wallet_descriptor = wallet.public_descriptor(KeychainKind::External).cloned();
-                if wallet_descriptor != Some(expected_descriptor.clone()) {
-                    return Err(NewOrLoadError::LoadedDescriptorDoesNotMatch {
-                        got: wallet_descriptor,
-                        keychain: KeychainKind::External,
-                    });
-                }
-                // if expected descriptor has private keys add them as new signers
-                if !expected_descriptor_keymap.is_empty() {
-                    let signer_container = SignersContainer::build(
-                        expected_descriptor_keymap,
-                        &expected_descriptor,
-                        &wallet.secp,
-                    );
-                    signer_container.signers().into_iter().for_each(|signer| {
-                        wallet.add_signer(
-                            KeychainKind::External,
-                            SignerOrdering::default(),
-                            signer.clone(),
-                        )
-                    });
-                }
-
-                let expected_change_descriptor = if let Some(c) = change_descriptor {
-                    Some(
-                        c.into_wallet_descriptor(&wallet.secp, network)
-                            .map_err(NewOrLoadError::Descriptor)?,
-                    )
-                } else {
-                    None
-                };
-                let wallet_change_descriptor =
-                    wallet.public_descriptor(KeychainKind::Internal).cloned();
-
-                match (expected_change_descriptor, wallet_change_descriptor) {
-                    (Some((expected_descriptor, expected_keymap)), Some(wallet_descriptor))
-                        if wallet_descriptor == expected_descriptor =>
-                    {
-                        // if expected change descriptor has private keys add them as new signers
-                        if !expected_keymap.is_empty() {
-                            let signer_container = SignersContainer::build(
-                                expected_keymap,
-                                &expected_descriptor,
-                                &wallet.secp,
-                            );
-                            signer_container.signers().into_iter().for_each(|signer| {
-                                wallet.add_signer(
-                                    KeychainKind::Internal,
-                                    SignerOrdering::default(),
-                                    signer.clone(),
-                                )
-                            });
-                        }
-                    }
-                    (None, None) => (),
-                    (_, wallet_descriptor) => {
-                        return Err(NewOrLoadError::LoadedDescriptorDoesNotMatch {
-                            got: wallet_descriptor,
-                            keychain: KeychainKind::Internal,
-                        });
-                    }
-                }
-
-                Ok(wallet)
-            }
-            None => Self::new_with_genesis_hash(
-                descriptor,
-                change_descriptor,
-                db,
-                network,
-                genesis_hash,
-            )
-            .map_err(|e| match e {
-                NewError::NonEmptyDatabase => {
-                    unreachable!("database is already checked to have no data")
-                }
-                NewError::Descriptor(e) => NewOrLoadError::Descriptor(e),
-                NewError::Persist(e) => NewOrLoadError::Persist(e),
-            }),
-        }
-    }
-
-    /// Get the Bitcoin network the wallet is using.
-    pub fn network(&self) -> Network {
-        self.network
-    }
-
-    /// Iterator over all keychains in this wallet
-    pub fn keychains(&self) -> impl Iterator<Item = (&KeychainKind, &ExtendedDescriptor)> {
-        self.indexed_graph.index.keychains()
-    }
-
-    /// Peek an address of the given `keychain` at `index` without revealing it.
-    ///
-    /// For non-wildcard descriptors this returns the same address at every provided index.
-    ///
-    /// # Panics
-    ///
-    /// This panics when the caller requests for an address of derivation index greater than the
-    /// [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) max index.
-    pub fn peek_address(&self, keychain: KeychainKind, mut index: u32) -> AddressInfo {
-        let keychain = self.map_keychain(keychain);
-        let mut spk_iter = self
-            .indexed_graph
-            .index
-            .unbounded_spk_iter(&keychain)
-            .expect("Must exist (we called map_keychain)");
-        if !spk_iter.descriptor().has_wildcard() {
-            index = 0;
-        }
-        let (index, spk) = spk_iter
-            .nth(index as usize)
-            .expect("derivation index is out of bounds");
-
-        AddressInfo {
-            index,
-            address: Address::from_script(&spk, self.network).expect("must have address form"),
-            keychain,
-        }
-    }
-
-    /// Attempt to reveal the next address of the given `keychain`.
-    ///
-    /// This will increment the internal derivation index. If the keychain's descriptor doesn't
-    /// contain a wildcard or every address is already revealed up to the maximum derivation
-    /// index defined in [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki),
-    /// then returns the last revealed address.
-    ///
-    /// # Errors
-    ///
-    /// If writing to persistent storage fails.
-    pub fn reveal_next_address(&mut self, keychain: KeychainKind) -> anyhow::Result<AddressInfo> {
-        let keychain = self.map_keychain(keychain);
-        let ((index, spk), index_changeset) = self
-            .indexed_graph
-            .index
-            .reveal_next_spk(&keychain)
-            .expect("Must exist (we called map_keychain)");
-
-        self.persist
-            .stage_and_commit(indexed_tx_graph::ChangeSet::from(index_changeset).into())?;
-
-        Ok(AddressInfo {
-            index,
-            address: Address::from_script(spk, self.network).expect("must have address form"),
-            keychain,
-        })
-    }
-
-    /// Reveal addresses up to and including the target `index` and return an iterator
-    /// of newly revealed addresses.
-    ///
-    /// If the target `index` is unreachable, we make a best effort to reveal up to the last
-    /// possible index. If all addresses up to the given `index` are already revealed, then
-    /// no new addresses are returned.
-    ///
-    /// # Errors
-    ///
-    /// If writing to persistent storage fails.
-    pub fn reveal_addresses_to(
-        &mut self,
-        keychain: KeychainKind,
-        index: u32,
-    ) -> anyhow::Result<impl Iterator<Item = AddressInfo> + '_> {
-        let keychain = self.map_keychain(keychain);
-        let (spk_iter, index_changeset) = self
-            .indexed_graph
-            .index
-            .reveal_to_target(&keychain, index)
-            .expect("must exist (we called map_keychain)");
-
-        self.persist
-            .stage_and_commit(indexed_tx_graph::ChangeSet::from(index_changeset).into())?;
-
-        Ok(spk_iter.map(move |(index, spk)| AddressInfo {
-            index,
-            address: Address::from_script(&spk, self.network).expect("must have address form"),
-            keychain,
-        }))
-    }
-
-    /// Get the next unused address for the given `keychain`, i.e. the address with the lowest
-    /// derivation index that hasn't been used.
-    ///
-    /// This will attempt to derive and reveal a new address if no newly revealed addresses
-    /// are available. See also [`reveal_next_address`](Self::reveal_next_address).
-    ///
-    /// # Errors
-    ///
-    /// If writing to persistent storage fails.
-    pub fn next_unused_address(&mut self, keychain: KeychainKind) -> anyhow::Result<AddressInfo> {
-        let keychain = self.map_keychain(keychain);
-        let ((index, spk), index_changeset) = self
-            .indexed_graph
-            .index
-            .next_unused_spk(&keychain)
-            .expect("must exist (we called map_keychain)");
-
-        self.persist
-            .stage_and_commit(indexed_tx_graph::ChangeSet::from(index_changeset).into())?;
-
-        Ok(AddressInfo {
-            index,
-            address: Address::from_script(spk, self.network).expect("must have address form"),
-            keychain,
-        })
-    }
-
-    /// Marks an address used of the given `keychain` at `index`.
-    ///
-    /// Returns whether the given index was present and then removed from the unused set.
-    pub fn mark_used(&mut self, keychain: KeychainKind, index: u32) -> bool {
-        self.indexed_graph.index.mark_used(keychain, index)
-    }
-
-    /// Undoes the effect of [`mark_used`] and returns whether the `index` was inserted
-    /// back into the unused set.
-    ///
-    /// Since this is only a superficial marker, it will have no effect if the address at the given
-    /// `index` was actually used, i.e. the wallet has previously indexed a tx output for the
-    /// derived spk.
-    ///
-    /// [`mark_used`]: Self::mark_used
-    pub fn unmark_used(&mut self, keychain: KeychainKind, index: u32) -> bool {
-        self.indexed_graph.index.unmark_used(keychain, index)
-    }
-
-    /// List addresses that are revealed but unused.
-    ///
-    /// Note if the returned iterator is empty you can reveal more addresses
-    /// by using [`reveal_next_address`](Self::reveal_next_address) or
-    /// [`reveal_addresses_to`](Self::reveal_addresses_to).
-    pub fn list_unused_addresses(
-        &self,
-        keychain: KeychainKind,
-    ) -> impl DoubleEndedIterator<Item = AddressInfo> + '_ {
-        let keychain = self.map_keychain(keychain);
-        self.indexed_graph
-            .index
-            .unused_keychain_spks(&keychain)
-            .map(move |(index, spk)| AddressInfo {
-                index,
-                address: Address::from_script(spk, self.network).expect("must have address form"),
-                keychain,
-            })
-    }
-
-    /// Return whether or not a `script` is part of this wallet (either internal or external)
-    pub fn is_mine(&self, script: &Script) -> bool {
-        self.indexed_graph.index.index_of_spk(script).is_some()
-    }
-
-    /// 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.indexed_graph.index.index_of_spk(spk)
-    }
-
-    /// Return the list of unspent outputs of this wallet
-    pub fn list_unspent(&self) -> impl Iterator<Item = LocalOutput> + '_ {
-        self.indexed_graph
-            .graph()
-            .filter_chain_unspents(
-                &self.chain,
-                self.chain.tip().block_id(),
-                self.indexed_graph.index.outpoints(),
-            )
-            .map(|((k, i), full_txo)| new_local_utxo(k, i, full_txo))
-    }
-
-    /// List all relevant outputs (includes both spent and unspent, confirmed and unconfirmed).
-    ///
-    /// To list only unspent outputs (UTXOs), use [`Wallet::list_unspent`] instead.
-    pub fn list_output(&self) -> impl Iterator<Item = LocalOutput> + '_ {
-        self.indexed_graph
-            .graph()
-            .filter_chain_txouts(
-                &self.chain,
-                self.chain.tip().block_id(),
-                self.indexed_graph.index.outpoints(),
-            )
-            .map(|((k, i), full_txo)| new_local_utxo(k, i, full_txo))
-    }
-
-    /// Get all the checkpoints the wallet is currently storing indexed by height.
-    pub fn checkpoints(&self) -> CheckPointIter {
-        self.chain.iter_checkpoints()
-    }
-
-    /// Returns the latest checkpoint.
-    pub fn latest_checkpoint(&self) -> CheckPoint {
-        self.chain.tip()
-    }
-
-    /// Get unbounded script pubkey iterators for both `Internal` and `External` keychains.
-    ///
-    /// This is intended 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 gap*.
-    ///
-    /// Note carefully that iterators go over **all** script pubkeys on the keychains (not what
-    /// script pubkeys the wallet is storing internally).
-    pub fn all_unbounded_spk_iters(
-        &self,
-    ) -> BTreeMap<KeychainKind, impl Iterator<Item = (u32, ScriptBuf)> + Clone> {
-        self.indexed_graph.index.all_unbounded_spk_iters()
-    }
-
-    /// Get an unbounded script pubkey iterator for the given `keychain`.
-    ///
-    /// See [`all_unbounded_spk_iters`] for more documentation
-    ///
-    /// [`all_unbounded_spk_iters`]: Self::all_unbounded_spk_iters
-    pub fn unbounded_spk_iter(
-        &self,
-        keychain: KeychainKind,
-    ) -> impl Iterator<Item = (u32, ScriptBuf)> + Clone {
-        let keychain = self.map_keychain(keychain);
-        self.indexed_graph
-            .index
-            .unbounded_spk_iter(&keychain)
-            .expect("Must exist (we called map_keychain)")
-    }
-
-    /// Returns the utxo owned by this wallet corresponding to `outpoint` if it exists in the
-    /// wallet's database.
-    pub fn get_utxo(&self, op: OutPoint) -> Option<LocalOutput> {
-        let (keychain, index, _) = self.indexed_graph.index.txout(op)?;
-        self.indexed_graph
-            .graph()
-            .filter_chain_unspents(
-                &self.chain,
-                self.chain.tip().block_id(),
-                core::iter::once(((), op)),
-            )
-            .map(|(_, full_txo)| new_local_utxo(keychain, index, full_txo))
-            .next()
-    }
-
-    /// Inserts a [`TxOut`] at [`OutPoint`] into the wallet's transaction graph.
-    ///
-    /// This is used for providing a previous output's value so that we can use [`calculate_fee`]
-    /// or [`calculate_fee_rate`] on a given transaction. Outputs inserted with this method will
-    /// not be returned in [`list_unspent`] or [`list_output`].
-    ///
-    /// Any inserted `TxOut`s are not persisted until [`commit`] is called.
-    ///
-    /// **WARNING:** This should only be used to add `TxOut`s that the wallet does not own. Only
-    /// insert `TxOut`s that you trust the values for!
-    ///
-    /// [`calculate_fee`]: Self::calculate_fee
-    /// [`calculate_fee_rate`]: Self::calculate_fee_rate
-    /// [`list_unspent`]: Self::list_unspent
-    /// [`list_output`]: Self::list_output
-    /// [`commit`]: Self::commit
-    pub fn insert_txout(&mut self, outpoint: OutPoint, txout: TxOut) {
-        let additions = self.indexed_graph.insert_txout(outpoint, txout);
-        self.persist.stage(ChangeSet::from(additions));
-    }
-
-    /// Calculates the fee of a given transaction. Returns 0 if `tx` is a coinbase transaction.
-    ///
-    /// To calculate the fee for a [`Transaction`] with inputs not owned by this wallet you must
-    /// manually insert the TxOut(s) into the tx graph using the [`insert_txout`] function.
-    ///
-    /// Note `tx` does not have to be in the graph for this to work.
-    ///
-    /// # Examples
-    ///
-    /// ```rust, no_run
-    /// # use bitcoin::Txid;
-    /// # use bdk::Wallet;
-    /// # let mut wallet: Wallet = todo!();
-    /// # let txid:Txid = todo!();
-    /// let tx = wallet.get_tx(txid).expect("transaction").tx_node.tx;
-    /// let fee = wallet.calculate_fee(&tx).expect("fee");
-    /// ```
-    ///
-    /// ```rust, no_run
-    /// # use bitcoin::Psbt;
-    /// # use bdk::Wallet;
-    /// # let mut wallet: Wallet = todo!();
-    /// # let mut psbt: Psbt = todo!();
-    /// let tx = &psbt.clone().extract_tx().expect("tx");
-    /// let fee = wallet.calculate_fee(tx).expect("fee");
-    /// ```
-    /// [`insert_txout`]: Self::insert_txout
-    pub fn calculate_fee(&self, tx: &Transaction) -> Result<u64, CalculateFeeError> {
-        self.indexed_graph.graph().calculate_fee(tx)
-    }
-
-    /// Calculate the [`FeeRate`] for a given transaction.
-    ///
-    /// To calculate the fee rate for a [`Transaction`] with inputs not owned by this wallet you must
-    /// manually insert the TxOut(s) into the tx graph using the [`insert_txout`] function.
-    ///
-    /// Note `tx` does not have to be in the graph for this to work.
-    ///
-    /// # Examples
-    ///
-    /// ```rust, no_run
-    /// # use bitcoin::Txid;
-    /// # use bdk::Wallet;
-    /// # let mut wallet: Wallet = todo!();
-    /// # let txid:Txid = todo!();
-    /// let tx = wallet.get_tx(txid).expect("transaction").tx_node.tx;
-    /// let fee_rate = wallet.calculate_fee_rate(&tx).expect("fee rate");
-    /// ```
-    ///
-    /// ```rust, no_run
-    /// # use bitcoin::Psbt;
-    /// # use bdk::Wallet;
-    /// # let mut wallet: Wallet = todo!();
-    /// # let mut psbt: Psbt = todo!();
-    /// let tx = &psbt.clone().extract_tx().expect("tx");
-    /// let fee_rate = wallet.calculate_fee_rate(tx).expect("fee rate");
-    /// ```
-    /// [`insert_txout`]: Self::insert_txout
-    pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result<FeeRate, CalculateFeeError> {
-        self.calculate_fee(tx)
-            .map(|fee| Amount::from_sat(fee) / tx.weight())
-    }
-
-    /// Compute the `tx`'s sent and received [`Amount`]s.
-    ///
-    /// This method returns a tuple `(sent, received)`. Sent is the sum of the txin amounts
-    /// that spend from previous txouts tracked by this wallet. Received is the summation
-    /// of this tx's outputs that send to script pubkeys tracked by this wallet.
-    ///
-    /// # Examples
-    ///
-    /// ```rust, no_run
-    /// # use bitcoin::Txid;
-    /// # use bdk::Wallet;
-    /// # let mut wallet: Wallet = todo!();
-    /// # let txid:Txid = todo!();
-    /// let tx = wallet.get_tx(txid).expect("tx exists").tx_node.tx;
-    /// let (sent, received) = wallet.sent_and_received(&tx);
-    /// ```
-    ///
-    /// ```rust, no_run
-    /// # use bitcoin::Psbt;
-    /// # use bdk::Wallet;
-    /// # let mut wallet: Wallet = todo!();
-    /// # let mut psbt: Psbt = todo!();
-    /// let tx = &psbt.clone().extract_tx().expect("tx");
-    /// let (sent, received) = wallet.sent_and_received(tx);
-    /// ```
-    pub fn sent_and_received(&self, tx: &Transaction) -> (Amount, Amount) {
-        self.indexed_graph.index.sent_and_received(tx, ..)
-    }
-
-    /// Get a single transaction from the wallet as a [`CanonicalTx`] (if the transaction exists).
-    ///
-    /// `CanonicalTx` contains the full transaction alongside meta-data such as:
-    /// * Blocks that the transaction is [`Anchor`]ed in. These may or may not be blocks that exist
-    ///   in the best chain.
-    /// * The [`ChainPosition`] of the transaction in the best chain - whether the transaction is
-    ///   confirmed or unconfirmed. If the transaction is confirmed, the anchor which proves the
-    ///   confirmation is provided. If the transaction is unconfirmed, the unix timestamp of when
-    ///   the transaction was last seen in the mempool is provided.
-    ///
-    /// ```rust, no_run
-    /// use bdk::{chain::ChainPosition, Wallet};
-    /// use bdk_chain::Anchor;
-    /// # let wallet: Wallet = todo!();
-    /// # let my_txid: bitcoin::Txid = todo!();
-    ///
-    /// let canonical_tx = wallet.get_tx(my_txid).expect("panic if tx does not exist");
-    ///
-    /// // get reference to full transaction
-    /// println!("my tx: {:#?}", canonical_tx.tx_node.tx);
-    ///
-    /// // list all transaction anchors
-    /// for anchor in canonical_tx.tx_node.anchors {
-    ///     println!(
-    ///         "tx is anchored by block of hash {}",
-    ///         anchor.anchor_block().hash
-    ///     );
-    /// }
-    ///
-    /// // get confirmation status of transaction
-    /// match canonical_tx.chain_position {
-    ///     ChainPosition::Confirmed(anchor) => println!(
-    ///         "tx is confirmed at height {}, we know this since {}:{} is in the best chain",
-    ///         anchor.confirmation_height, anchor.anchor_block.height, anchor.anchor_block.hash,
-    ///     ),
-    ///     ChainPosition::Unconfirmed(last_seen) => println!(
-    ///         "tx is last seen at {}, it is unconfirmed as it is not anchored in the best chain",
-    ///         last_seen,
-    ///     ),
-    /// }
-    /// ```
-    ///
-    /// [`Anchor`]: bdk_chain::Anchor
-    pub fn get_tx(
-        &self,
-        txid: Txid,
-    ) -> Option<CanonicalTx<'_, Arc<Transaction>, ConfirmationTimeHeightAnchor>> {
-        let graph = self.indexed_graph.graph();
-
-        Some(CanonicalTx {
-            chain_position: graph.get_chain_position(
-                &self.chain,
-                self.chain.tip().block_id(),
-                txid,
-            )?,
-            tx_node: graph.get_tx_node(txid)?,
-        })
-    }
-
-    /// 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).
-    ///
-    /// [`commit`]: Self::commit
-    pub fn insert_checkpoint(
-        &mut self,
-        block_id: BlockId,
-    ) -> Result<bool, local_chain::AlterCheckPointError> {
-        let changeset = self.chain.insert_block(block_id)?;
-        let changed = !changeset.is_empty();
-        self.persist.stage(changeset.into());
-        Ok(changed)
-    }
-
-    /// Add a transaction to the wallet's internal view of the chain. This stages but does not
-    /// [`commit`] the change.
-    ///
-    /// Returns whether anything changed with the transaction insertion (e.g. `false` if the
-    /// transaction was already inserted at the same position).
-    ///
-    /// A `tx` can be rejected if `position` has a height greater than the [`latest_checkpoint`].
-    /// Therefore you should use [`insert_checkpoint`] to insert new checkpoints before manually
-    /// inserting new transactions.
-    ///
-    /// **WARNING:** If `position` is confirmed, we anchor the `tx` to a the lowest checkpoint that
-    /// is >= the `position`'s height. The caller is responsible for ensuring the `tx` exists in our
-    /// local view of the best chain's history.
-    ///
-    /// [`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, InsertTxError> {
-        let (anchor, last_seen) = match position {
-            ConfirmationTime::Confirmed { height, time } => {
-                // anchor tx to checkpoint with lowest height that is >= position's height
-                let anchor = self
-                    .chain
-                    .range(height..)
-                    .last()
-                    .ok_or(InsertTxError::ConfirmationHeightCannotBeGreaterThanTip {
-                        tip_height: self.chain.tip().height(),
-                        tx_height: height,
-                    })
-                    .map(|anchor_cp| ConfirmationTimeHeightAnchor {
-                        anchor_block: anchor_cp.block_id(),
-                        confirmation_height: height,
-                        confirmation_time: time,
-                    })?;
-
-                (Some(anchor), None)
-            }
-            ConfirmationTime::Unconfirmed { last_seen } => (None, Some(last_seen)),
-        };
-
-        let mut changeset = ChangeSet::default();
-        let txid = tx.txid();
-        changeset.append(self.indexed_graph.insert_tx(tx).into());
-        if let Some(anchor) = anchor {
-            changeset.append(self.indexed_graph.insert_anchor(txid, anchor).into());
-        }
-        if let Some(last_seen) = last_seen {
-            changeset.append(self.indexed_graph.insert_seen_at(txid, last_seen).into());
-        }
-
-        let changed = !changeset.is_empty();
-        self.persist.stage(changeset);
-        Ok(changed)
-    }
-
-    /// Iterate over the transactions in the wallet.
-    pub fn transactions(
-        &self,
-    ) -> impl Iterator<Item = CanonicalTx<'_, Arc<Transaction>, ConfirmationTimeHeightAnchor>> + '_
-    {
-        self.indexed_graph
-            .graph()
-            .list_chain_txs(&self.chain, self.chain.tip().block_id())
-    }
-
-    /// Return the balance, separated into available, trusted-pending, untrusted-pending and immature
-    /// values.
-    pub fn get_balance(&self) -> Balance {
-        self.indexed_graph.graph().balance(
-            &self.chain,
-            self.chain.tip().block_id(),
-            self.indexed_graph.index.outpoints(),
-            |&(k, _), _| k == KeychainKind::Internal,
-        )
-    }
-
-    /// Add an external signer
-    ///
-    /// See [the `signer` module](signer) for an example.
-    pub fn add_signer(
-        &mut self,
-        keychain: KeychainKind,
-        ordering: SignerOrdering,
-        signer: Arc<dyn TransactionSigner>,
-    ) {
-        let signers = match keychain {
-            KeychainKind::External => Arc::make_mut(&mut self.signers),
-            KeychainKind::Internal => Arc::make_mut(&mut self.change_signers),
-        };
-
-        signers.add_external(signer.id(&self.secp), ordering, signer);
-    }
-
-    /// Get the signers
-    ///
-    /// ## Example
-    ///
-    /// ```
-    /// # use bdk::{Wallet, KeychainKind};
-    /// # use bdk::bitcoin::Network;
-    /// 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>>(())
-    /// ```
-    pub fn get_signers(&self, keychain: KeychainKind) -> Arc<SignersContainer> {
-        match keychain {
-            KeychainKind::External => Arc::clone(&self.signers),
-            KeychainKind::Internal => Arc::clone(&self.change_signers),
-        }
-    }
-
-    /// Start building a transaction.
-    ///
-    /// This returns a blank [`TxBuilder`] from which you can specify the parameters for the transaction.
-    ///
-    /// ## Example
-    ///
-    /// ```
-    /// # use std::str::FromStr;
-    /// # use bitcoin::*;
-    /// # use bdk::*;
-    /// # use bdk::wallet::ChangeSet;
-    /// # use bdk::wallet::error::CreateTxError;
-    /// # use bdk_persist::PersistBackend;
-    /// # use anyhow::Error;
-    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-    /// # let mut wallet = doctest_wallet!();
-    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
-    /// let psbt = {
-    ///    let mut builder =  wallet.build_tx();
-    ///    builder
-    ///        .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
-    ///    builder.finish()?
-    /// };
-    ///
-    /// // sign and broadcast ...
-    /// # Ok::<(), anyhow::Error>(())
-    /// ```
-    ///
-    /// [`TxBuilder`]: crate::TxBuilder
-    pub fn build_tx(&mut self) -> TxBuilder<'_, DefaultCoinSelectionAlgorithm, CreateTx> {
-        TxBuilder {
-            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>(
-        &mut self,
-        coin_selection: Cs,
-        params: TxParams,
-    ) -> Result<Psbt, CreateTxError> {
-        let keychains: BTreeMap<_, _> = self.indexed_graph.index.keychains().collect();
-        let external_descriptor = keychains.get(&KeychainKind::External).expect("must exist");
-        let internal_descriptor = keychains.get(&KeychainKind::Internal);
-
-        let external_policy = external_descriptor
-            .extract_policy(&self.signers, BuildSatisfaction::None, &self.secp)?
-            .unwrap();
-        let internal_policy = internal_descriptor
-            .as_ref()
-            .map(|desc| {
-                Ok::<_, CreateTxError>(
-                    desc.extract_policy(&self.change_signers, BuildSatisfaction::None, &self.secp)?
-                        .unwrap(),
-                )
-            })
-            .transpose()?;
-
-        // The policy allows spending external outputs, but it requires a policy path that hasn't been
-        // provided
-        if params.change_policy != tx_builder::ChangeSpendPolicy::OnlyChange
-            && external_policy.requires_path()
-            && params.external_policy_path.is_none()
-        {
-            return Err(CreateTxError::SpendingPolicyRequired(
-                KeychainKind::External,
-            ));
-        };
-        // Same for the internal_policy path, if present
-        if let Some(internal_policy) = &internal_policy {
-            if params.change_policy != tx_builder::ChangeSpendPolicy::ChangeForbidden
-                && internal_policy.requires_path()
-                && params.internal_policy_path.is_none()
-            {
-                return Err(CreateTxError::SpendingPolicyRequired(
-                    KeychainKind::Internal,
-                ));
-            };
-        }
-
-        let external_requirements = external_policy.get_condition(
-            params
-                .external_policy_path
-                .as_ref()
-                .unwrap_or(&BTreeMap::new()),
-        )?;
-        let internal_requirements = internal_policy
-            .map(|policy| {
-                Ok::<_, CreateTxError>(
-                    policy.get_condition(
-                        params
-                            .internal_policy_path
-                            .as_ref()
-                            .unwrap_or(&BTreeMap::new()),
-                    )?,
-                )
-            })
-            .transpose()?;
-
-        let requirements =
-            external_requirements.merge(&internal_requirements.unwrap_or_default())?;
-
-        let version = match params.version {
-            Some(tx_builder::Version(0)) => return Err(CreateTxError::Version0),
-            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
-                return Err(CreateTxError::Version1Csv)
-            }
-            Some(tx_builder::Version(x)) => x,
-            None if requirements.csv.is_some() => 2,
-            None => 1,
-        };
-
-        // We use a match here instead of a unwrap_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 => {
-                let tip_height = self.chain.tip().height();
-                absolute::LockTime::from_height(tip_height).expect("invalid height")
-            }
-            Some(h) => h,
-        };
-
-        let lock_time = match params.locktime {
-            // When no nLockTime is specified, we try to prevent fee sniping, if possible
-            None => {
-                // Fee sniping can be partially prevented by setting the timelock
-                // to current_height. If we don't know the current_height,
-                // we default to 0.
-                let fee_sniping_height = current_height;
-
-                // We choose the biggest between the required nlocktime and the fee sniping
-                // height
-                match requirements.timelock {
-                    // No requirement, just use the fee_sniping_height
-                    None => fee_sniping_height,
-                    // There's a block-based requirement, but the value is lower than the fee_sniping_height
-                    Some(value @ absolute::LockTime::Blocks(_)) if value < fee_sniping_height => {
-                        fee_sniping_height
-                    }
-                    // There's a time-based requirement or a block-based requirement greater
-                    // than the fee_sniping_height use that value
-                    Some(value) => value,
-                }
-            }
-            // Specific nLockTime required and we have no constraints, so just set to that value
-            Some(x) if requirements.timelock.is_none() => x,
-            // Specific nLockTime required and it's compatible with the constraints
-            Some(x)
-                if requirements.timelock.unwrap().is_same_unit(x)
-                    && x >= requirements.timelock.unwrap() =>
-            {
-                x
-            }
-            // Invalid nLockTime required
-            Some(x) => {
-                return Err(CreateTxError::LockTime {
-                    requested: x,
-                    required: requirements.timelock.unwrap(),
-                })
-            }
-        };
-
-        // The nSequence to be by default for inputs unless an explicit sequence is specified.
-        let n_sequence = match (params.rbf, requirements.csv) {
-            // No RBF or CSV but there's an nLockTime, so the nSequence cannot be final
-            (None, None) if lock_time != absolute::LockTime::ZERO => {
-                Sequence::ENABLE_LOCKTIME_NO_RBF
-            }
-            // No RBF, CSV or nLockTime, make the transaction final
-            (None, None) => Sequence::MAX,
-
-            // No RBF requested, use the value from CSV. Note that this value is by definition
-            // non-final, so even if a timelock is enabled this nSequence is fine, hence why we
-            // don't bother checking for it here. The same is true for all the other branches below
-            (None, Some(csv)) => csv,
-
-            // RBF with a specific value but that value is too high
-            (Some(tx_builder::RbfValue::Value(rbf)), _) if !rbf.is_rbf() => {
-                return Err(CreateTxError::RbfSequence)
-            }
-            // RBF with a specific value requested, but the value is incompatible with CSV
-            (Some(tx_builder::RbfValue::Value(rbf)), Some(csv))
-                if !check_nsequence_rbf(rbf, csv) =>
-            {
-                return Err(CreateTxError::RbfSequenceCsv { rbf, csv })
-            }
-
-            // RBF enabled with the default value with CSV also enabled. CSV takes precedence
-            (Some(tx_builder::RbfValue::Default), Some(csv)) => csv,
-            // Valid RBF, either default or with a specific value. We ignore the `CSV` value
-            // because we've already checked it before
-            (Some(rbf), _) => rbf.get_value(),
-        };
-
-        let (fee_rate, mut fee_amount) = match params.fee_policy.unwrap_or_default() {
-            //FIXME: see https://github.com/bitcoindevkit/bdk/issues/256
-            FeePolicy::FeeAmount(fee) => {
-                if let Some(previous_fee) = params.bumping_fee {
-                    if fee < previous_fee.absolute {
-                        return Err(CreateTxError::FeeTooLow {
-                            required: previous_fee.absolute,
-                        });
-                    }
-                }
-                (FeeRate::ZERO, fee)
-            }
-            FeePolicy::FeeRate(rate) => {
-                if let Some(previous_fee) = params.bumping_fee {
-                    let required_feerate = FeeRate::from_sat_per_kwu(
-                        previous_fee.rate.to_sat_per_kwu()
-                            + FeeRate::BROADCAST_MIN.to_sat_per_kwu(), // +1 sat/vb
-                    );
-                    if rate < required_feerate {
-                        return Err(CreateTxError::FeeRateTooLow {
-                            required: required_feerate,
-                        });
-                    }
-                }
-                (rate, 0)
-            }
-        };
-
-        let mut tx = Transaction {
-            version: transaction::Version::non_standard(version),
-            lock_time,
-            input: vec![],
-            output: vec![],
-        };
-
-        if params.manually_selected_only && params.utxos.is_empty() {
-            return Err(CreateTxError::NoUtxosSelected);
-        }
-
-        // we keep it as a float while we accumulate it, and only round it at the end
-        let mut outgoing: u64 = 0;
-        let mut received: u64 = 0;
-
-        let recipients = params.recipients.iter().map(|(r, v)| (r, *v));
-
-        for (index, (script_pubkey, value)) in recipients.enumerate() {
-            if !params.allow_dust
-                && value.is_dust(script_pubkey)
-                && !script_pubkey.is_provably_unspendable()
-            {
-                return Err(CreateTxError::OutputBelowDustLimit(index));
-            }
-
-            if self.is_mine(script_pubkey) {
-                received += value;
-            }
-
-            let new_out = TxOut {
-                script_pubkey: script_pubkey.clone(),
-                value: Amount::from_sat(value),
-            };
-
-            tx.output.push(new_out);
-
-            outgoing += value;
-        }
-
-        fee_amount += (fee_rate * tx.weight()).to_sat();
-
-        if params.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
-            && internal_descriptor.is_none()
-        {
-            return Err(CreateTxError::ChangePolicyDescriptor);
-        }
-
-        let (required_utxos, optional_utxos) =
-            self.preselect_utxos(&params, Some(current_height.to_consensus_u32()));
-
-        // get drain script
-        let drain_script = match params.drain_to {
-            Some(ref drain_recipient) => drain_recipient.clone(),
-            None => {
-                let change_keychain = self.map_keychain(KeychainKind::Internal);
-                let ((index, spk), index_changeset) = self
-                    .indexed_graph
-                    .index
-                    .next_unused_spk(&change_keychain)
-                    .expect("Keychain exists (we called map_keychain)");
-                let spk = spk.into();
-                self.indexed_graph.index.mark_used(change_keychain, index);
-                self.persist
-                    .stage(ChangeSet::from(indexed_tx_graph::ChangeSet::from(
-                        index_changeset,
-                    )));
-                self.persist.commit().map_err(CreateTxError::Persist)?;
-                spk
-            }
-        };
-
-        let (required_utxos, optional_utxos) =
-            coin_selection::filter_duplicates(required_utxos, optional_utxos);
-
-        let coin_selection = coin_selection.coin_select(
-            required_utxos,
-            optional_utxos,
-            fee_rate,
-            outgoing + fee_amount,
-            &drain_script,
-        )?;
-        fee_amount += coin_selection.fee_amount;
-        let excess = &coin_selection.excess;
-
-        tx.input = coin_selection
-            .selected
-            .iter()
-            .map(|u| bitcoin::TxIn {
-                previous_output: u.outpoint(),
-                script_sig: ScriptBuf::default(),
-                sequence: u.sequence().unwrap_or(n_sequence),
-                witness: Witness::new(),
-            })
-            .collect();
-
-        if tx.output.is_empty() {
-            // Uh oh, our transaction has no outputs.
-            // We allow this when:
-            // - We have a drain_to address and the utxos we must spend (this happens,
-            // for example, when we RBF)
-            // - We have a drain_to address and drain_wallet set
-            // Otherwise, we don't know who we should send the funds to, and how much
-            // we should send!
-            if params.drain_to.is_some() && (params.drain_wallet || !params.utxos.is_empty()) {
-                if let NoChange {
-                    dust_threshold,
-                    remaining_amount,
-                    change_fee,
-                } = excess
-                {
-                    return Err(CreateTxError::InsufficientFunds {
-                        needed: *dust_threshold,
-                        available: remaining_amount.saturating_sub(*change_fee),
-                    });
-                }
-            } else {
-                return Err(CreateTxError::NoRecipients);
-            }
-        }
-
-        match excess {
-            NoChange {
-                remaining_amount, ..
-            } => fee_amount += remaining_amount,
-            Change { amount, fee } => {
-                if self.is_mine(&drain_script) {
-                    received += amount;
-                }
-                fee_amount += fee;
-
-                // create drain output
-                let drain_output = TxOut {
-                    value: Amount::from_sat(*amount),
-                    script_pubkey: drain_script,
-                };
-
-                // TODO: We should pay attention when adding a new output: this might increase
-                // the length of the "number of vouts" parameter by 2 bytes, potentially making
-                // our feerate too low
-                tx.output.push(drain_output);
-            }
-        };
-
-        // sort input/outputs according to the chosen algorithm
-        params.ordering.sort_tx(&mut tx);
-
-        let psbt = self.complete_transaction(tx, coin_selection.selected, params)?;
-        Ok(psbt)
-    }
-
-    /// 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.
-    ///
-    /// ## Example
-    ///
-    /// ```no_run
-    /// # // TODO: remove norun -- bumping fee seems to need the tx in the wallet database first.
-    /// # use std::str::FromStr;
-    /// # use bitcoin::*;
-    /// # use bdk::*;
-    /// # use bdk::wallet::ChangeSet;
-    /// # use bdk::wallet::error::CreateTxError;
-    /// # use bdk_persist::PersistBackend;
-    /// # use anyhow::Error;
-    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-    /// # let mut wallet = doctest_wallet!();
-    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
-    /// let mut psbt = {
-    ///     let mut builder = wallet.build_tx();
-    ///     builder
-    ///         .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
-    ///         .enable_rbf();
-    ///     builder.finish()?
-    /// };
-    /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
-    /// let tx = psbt.clone().extract_tx().expect("tx");
-    /// // broadcast tx but it's taking too long to confirm so we want to bump the fee
-    /// let mut psbt =  {
-    ///     let mut builder = wallet.build_fee_bump(tx.txid())?;
-    ///     builder
-    ///         .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"));
-    ///     builder.finish()?
-    /// };
-    ///
-    /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
-    /// let fee_bumped_tx = psbt.extract_tx();
-    /// // broadcast fee_bumped_tx to replace original
-    /// # Ok::<(), anyhow::Error>(())
-    /// ```
-    // TODO: support for merging multiple transactions while bumping the fees
-    pub fn build_fee_bump(
-        &mut self,
-        txid: Txid,
-    ) -> Result<TxBuilder<'_, DefaultCoinSelectionAlgorithm, BumpFee>, BuildFeeBumpError> {
-        let graph = self.indexed_graph.graph();
-        let txout_index = &self.indexed_graph.index;
-        let chain_tip = self.chain.tip().block_id();
-
-        let mut tx = graph
-            .get_tx(txid)
-            .ok_or(BuildFeeBumpError::TransactionNotFound(txid))?
-            .as_ref()
-            .clone();
-
-        let pos = graph
-            .get_chain_position(&self.chain, chain_tip, txid)
-            .ok_or(BuildFeeBumpError::TransactionNotFound(txid))?;
-        if let ChainPosition::Confirmed(_) = pos {
-            return Err(BuildFeeBumpError::TransactionConfirmed(txid));
-        }
-
-        if !tx
-            .input
-            .iter()
-            .any(|txin| txin.sequence.to_consensus_u32() <= 0xFFFFFFFD)
-        {
-            return Err(BuildFeeBumpError::IrreplaceableTransaction(tx.txid()));
-        }
-
-        let fee = self
-            .calculate_fee(&tx)
-            .map_err(|_| BuildFeeBumpError::FeeRateUnavailable)?;
-        let fee_rate = self
-            .calculate_fee_rate(&tx)
-            .map_err(|_| BuildFeeBumpError::FeeRateUnavailable)?;
-
-        // 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<_, BuildFeeBumpError> {
-                let prev_tx = graph
-                    .get_tx(txin.previous_output.txid)
-                    .ok_or(BuildFeeBumpError::UnknownUtxo(txin.previous_output))?;
-                let txout = &prev_tx.output[txin.previous_output.vout as usize];
-
-                let confirmation_time: ConfirmationTime = graph
-                    .get_chain_position(&self.chain, chain_tip, txin.previous_output.txid)
-                    .ok_or(BuildFeeBumpError::UnknownUtxo(txin.previous_output))?
-                    .cloned()
-                    .into();
-
-                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_weight_to_satisfy()
-                            .unwrap();
-                        WeightedUtxo {
-                            utxo: Utxo::Local(LocalOutput {
-                                outpoint: txin.previous_output,
-                                txout: txout.clone(),
-                                keychain,
-                                is_spent: true,
-                                derivation_index,
-                                confirmation_time,
-                            }),
-                            satisfaction_weight,
-                        }
-                    }
-                    None => {
-                        let satisfaction_weight =
-                            serialize(&txin.script_sig).len() * 4 + serialize(&txin.witness).len();
-                        WeightedUtxo {
-                            utxo: Utxo::Foreign {
-                                outpoint: txin.previous_output,
-                                sequence: Some(txin.sequence),
-                                psbt_input: Box::new(psbt::Input {
-                                    witness_utxo: Some(txout.clone()),
-                                    non_witness_utxo: Some(prev_tx.as_ref().clone()),
-                                    ..Default::default()
-                                }),
-                            },
-                            satisfaction_weight,
-                        }
-                    }
-                };
-
-                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.map_keychain(KeychainKind::Internal);
-                match txout_index.index_of_spk(&txout.script_pubkey) {
-                    Some((keychain, _)) if keychain == change_type => change_index = Some(index),
-                    _ => {}
-                }
-            }
-
-            if let Some(change_index) = change_index {
-                tx.output.remove(change_index);
-            }
-        }
-
-        let params = TxParams {
-            // TODO: figure out what rbf option should be?
-            version: Some(tx_builder::Version(tx.version.0)),
-            recipients: tx
-                .output
-                .into_iter()
-                .map(|txout| (txout.script_pubkey, txout.value.to_sat()))
-                .collect(),
-            utxos: original_utxos,
-            bumping_fee: Some(tx_builder::PreviousFee {
-                absolute: fee,
-                rate: fee_rate,
-            }),
-            ..Default::default()
-        };
-
-        Ok(TxBuilder {
-            wallet: alloc::rc::Rc::new(core::cell::RefCell::new(self)),
-            params,
-            coin_selection: DefaultCoinSelectionAlgorithm::default(),
-            phantom: core::marker::PhantomData,
-        })
-    }
-
-    /// 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*
-    /// signers will follow the options, but the "software signers" (WIF keys and `xprv`) defined
-    /// in this library will.
-    ///
-    /// ## Example
-    ///
-    /// ```
-    /// # use std::str::FromStr;
-    /// # use bitcoin::*;
-    /// # use bdk::*;
-    /// # use bdk::wallet::ChangeSet;
-    /// # use bdk::wallet::error::CreateTxError;
-    /// # use bdk_persist::PersistBackend;
-    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-    /// # let mut wallet = doctest_wallet!();
-    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
-    /// let mut psbt = {
-    ///     let mut builder = wallet.build_tx();
-    ///     builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
-    ///     builder.finish()?
-    /// };
-    /// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
-    /// assert!(finalized, "we should have signed all the inputs");
-    /// # Ok::<(),anyhow::Error>(())
-    pub fn sign(&self, psbt: &mut Psbt, sign_options: SignOptions) -> Result<bool, SignerError> {
-        // This adds all the PSBT metadata for the inputs, which will help us later figure out how
-        // to derive our keys
-        self.update_psbt_with_descriptor(psbt)
-            .map_err(SignerError::MiniscriptPsbt)?;
-
-        // If we aren't allowed to use `witness_utxo`, ensure that every input (except p2tr and finalized ones)
-        // has the `non_witness_utxo`
-        if !sign_options.trust_witness_utxo
-            && psbt
-                .inputs
-                .iter()
-                .filter(|i| i.final_script_witness.is_none() && i.final_script_sig.is_none())
-                .filter(|i| i.tap_internal_key.is_none() && i.tap_merkle_root.is_none())
-                .any(|i| i.non_witness_utxo.is_none())
-        {
-            return Err(SignerError::MissingNonWitnessUtxo);
-        }
-
-        // If the user hasn't explicitly opted-in, refuse to sign the transaction unless every input
-        // is using `SIGHASH_ALL` or `SIGHASH_DEFAULT` for taproot
-        if !sign_options.allow_all_sighashes
-            && !psbt.inputs.iter().all(|i| {
-                i.sighash_type.is_none()
-                    || i.sighash_type == Some(EcdsaSighashType::All.into())
-                    || i.sighash_type == Some(TapSighashType::All.into())
-                    || i.sighash_type == Some(TapSighashType::Default.into())
-            })
-        {
-            return Err(SignerError::NonStandardSighash);
-        }
-
-        for signer in self
-            .signers
-            .signers()
-            .iter()
-            .chain(self.change_signers.signers().iter())
-        {
-            signer.sign_transaction(psbt, &sign_options, &self.secp)?;
-        }
-
-        // attempt to finalize
-        if sign_options.try_finalize {
-            self.finalize_psbt(psbt, sign_options)
-        } else {
-            Ok(false)
-        }
-    }
-
-    /// Return the spending policies for the wallet's descriptor
-    pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, DescriptorError> {
-        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),
-        }
-    }
-
-    /// 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
-    pub fn public_descriptor(&self, keychain: KeychainKind) -> Option<&ExtendedDescriptor> {
-        self.indexed_graph
-            .index
-            .keychains()
-            .find(|(k, _)| *k == &keychain)
-            .map(|(_, d)| d)
-    }
-
-    /// 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](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#Input_Finalizer)
-    /// 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.
-    pub fn finalize_psbt(
-        &self,
-        psbt: &mut Psbt,
-        sign_options: SignOptions,
-    ) -> Result<bool, SignerError> {
-        let chain_tip = self.chain.tip().block_id();
-
-        let tx = &psbt.unsigned_tx;
-        let mut finished = true;
-
-        for (n, input) in tx.input.iter().enumerate() {
-            let psbt_input = &psbt
-                .inputs
-                .get(n)
-                .ok_or(SignerError::InputIndexOutOfRange)?;
-            if psbt_input.final_script_sig.is_some() || psbt_input.final_script_witness.is_some() {
-                continue;
-            }
-            let confirmation_height = self
-                .indexed_graph
-                .graph()
-                .get_chain_position(&self.chain, chain_tip, input.previous_output.txid)
-                .map(|chain_position| match chain_position {
-                    ChainPosition::Confirmed(a) => a.confirmation_height,
-                    ChainPosition::Unconfirmed(_) => u32::MAX,
-                });
-            let current_height = sign_options
-                .assume_height
-                .unwrap_or_else(|| self.chain.tip().height());
-
-            // - Try to derive the descriptor by looking at the txout. If it's in our database, we
-            //   know exactly which `keychain` to use, and which derivation index it is
-            // - If that fails, try to derive it by looking at the psbt input: the complete logic
-            //   is in `src/descriptor/mod.rs`, but it will basically look at `bip32_derivation`,
-            //   `redeem_script` and `witness_script` to determine the right derivation
-            // - If that also fails, it will try it on the internal descriptor, if present
-            let desc = psbt
-                .get_utxo_for(n)
-                .and_then(|txout| self.get_descriptor_for_txout(&txout))
-                .or_else(|| {
-                    self.indexed_graph.index.keychains().find_map(|(_, desc)| {
-                        desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n), &self.secp)
-                    })
-                });
-
-            match desc {
-                Some(desc) => {
-                    let mut tmp_input = bitcoin::TxIn::default();
-                    match desc.satisfy(
-                        &mut tmp_input,
-                        (
-                            PsbtInputSatisfier::new(psbt, n),
-                            After::new(Some(current_height), false),
-                            Older::new(Some(current_height), confirmation_height, false),
-                        ),
-                    ) {
-                        Ok(_) => {
-                            let psbt_input = &mut psbt.inputs[n];
-                            psbt_input.final_script_sig = Some(tmp_input.script_sig);
-                            psbt_input.final_script_witness = Some(tmp_input.witness);
-                            if sign_options.remove_partial_sigs {
-                                psbt_input.partial_sigs.clear();
-                            }
-                            if sign_options.remove_taproot_extras {
-                                // We just constructed the final witness, clear these fields.
-                                psbt_input.tap_key_sig = None;
-                                psbt_input.tap_script_sigs.clear();
-                                psbt_input.tap_scripts.clear();
-                                psbt_input.tap_key_origins.clear();
-                                psbt_input.tap_internal_key = None;
-                                psbt_input.tap_merkle_root = None;
-                            }
-                        }
-                        Err(_) => finished = false,
-                    }
-                }
-                None => finished = false,
-            }
-        }
-
-        if finished && sign_options.remove_taproot_extras {
-            for output in &mut psbt.outputs {
-                output.tap_key_origins.clear();
-            }
-        }
-
-        Ok(finished)
-    }
-
-    /// Return the secp256k1 context used for all signing operations
-    pub fn secp_ctx(&self) -> &SecpCtx {
-        &self.secp
-    }
-
-    /// Returns the descriptor used to create addresses for a particular `keychain`.
-    pub fn get_descriptor_for_keychain(&self, keychain: KeychainKind) -> &ExtendedDescriptor {
-        self.public_descriptor(self.map_keychain(keychain))
-            .expect("we mapped it to external if it doesn't exist")
-    }
-
-    /// 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.indexed_graph.index.last_revealed_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 {
-        let keychain = self.map_keychain(keychain);
-        self.indexed_graph
-            .index
-            .next_index(&keychain)
-            .expect("Keychain must exist (we called map_keychain)")
-            .0
-    }
-
-    /// 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.indexed_graph.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);
-            }
-        }
-    }
-
-    fn map_keychain(&self, keychain: KeychainKind) -> KeychainKind {
-        if keychain == KeychainKind::Internal
-            && self.public_descriptor(KeychainKind::Internal).is_none()
-        {
-            KeychainKind::External
-        } else {
-            keychain
-        }
-    }
-
-    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Option<DerivedDescriptor> {
-        let (keychain, child) = self
-            .indexed_graph
-            .index
-            .index_of_spk(&txout.script_pubkey)?;
-        let descriptor = self.get_descriptor_for_keychain(keychain);
-        descriptor.at_derivation_index(child).ok()
-    }
-
-    fn get_available_utxos(&self) -> Vec<(LocalOutput, usize)> {
-        self.list_unspent()
-            .map(|utxo| {
-                let keychain = utxo.keychain;
-                (utxo, {
-                    self.get_descriptor_for_keychain(keychain)
-                        .max_weight_to_satisfy()
-                        .unwrap()
-                })
-            })
-            .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.
-    fn preselect_utxos(
-        &self,
-        params: &TxParams,
-        current_height: Option<u32>,
-    ) -> (Vec<WeightedUtxo>, Vec<WeightedUtxo>) {
-        let TxParams {
-            change_policy,
-            unspendable,
-            utxos,
-            drain_wallet,
-            manually_selected_only,
-            bumping_fee,
-            ..
-        } = params;
-
-        let manually_selected = utxos.clone();
-        // we mandate confirmed transactions if we're bumping the fee
-        let must_only_use_confirmed_tx = bumping_fee.is_some();
-        let must_use_all_available = *drain_wallet;
-
-        let chain_tip = self.chain.tip().block_id();
-        //    must_spend <- manually selected utxos
-        //    may_spend  <- all other available utxos
-        let mut may_spend = self.get_available_utxos();
-
-        may_spend.retain(|may_spend| {
-            !manually_selected
-                .iter()
-                .any(|manually_selected| manually_selected.utxo.outpoint() == may_spend.0.outpoint)
-        });
-        let mut must_spend = manually_selected;
-
-        // NOTE: we are intentionally ignoring `unspendable` here. i.e manual
-        // selection overrides unspendable.
-        if *manually_selected_only {
-            return (must_spend, vec![]);
-        }
-
-        let satisfies_confirmed = may_spend
-            .iter()
-            .map(|u| -> bool {
-                let txid = u.0.outpoint.txid;
-                let tx = match self.indexed_graph.graph().get_tx(txid) {
-                    Some(tx) => tx,
-                    None => return false,
-                };
-                let confirmation_time: ConfirmationTime = match self
-                    .indexed_graph
-                    .graph()
-                    .get_chain_position(&self.chain, chain_tip, txid)
-                {
-                    Some(chain_position) => chain_position.cloned().into(),
-                    None => return false,
-                };
-
-                // 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_coinbase() {
-                    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
-            })
-            .collect::<Vec<_>>();
-
-        let mut i = 0;
-        may_spend.retain(|u| {
-            let retain = change_policy.is_satisfied_by(&u.0)
-                && !unspendable.contains(&u.0.outpoint)
-                && satisfies_confirmed[i];
-            i += 1;
-            retain
-        });
-
-        let mut may_spend = may_spend
-            .into_iter()
-            .map(|(local_utxo, satisfaction_weight)| WeightedUtxo {
-                satisfaction_weight,
-                utxo: Utxo::Local(local_utxo),
-            })
-            .collect();
-
-        if must_use_all_available {
-            must_spend.append(&mut may_spend);
-        }
-
-        (must_spend, may_spend)
-    }
-
-    fn complete_transaction(
-        &self,
-        tx: Transaction,
-        selected: Vec<Utxo>,
-        params: TxParams,
-    ) -> Result<Psbt, CreateTxError> {
-        let mut psbt = Psbt::from_unsigned_tx(tx)?;
-
-        if params.add_global_xpubs {
-            let all_xpubs = self
-                .keychains()
-                .flat_map(|(_, desc)| desc.get_extended_keys())
-                .collect::<Vec<_>>();
-
-            for xpub in all_xpubs {
-                let origin = match xpub.origin {
-                    Some(origin) => origin,
-                    None if xpub.xkey.depth == 0 => {
-                        (xpub.root_fingerprint(&self.secp), vec![].into())
-                    }
-                    _ => return Err(CreateTxError::MissingKeyOrigin(xpub.xkey.to_string())),
-                };
-
-                psbt.xpub.insert(xpub.xkey, origin);
-            }
-        }
-
-        let mut lookup_output = selected
-            .into_iter()
-            .map(|utxo| (utxo.outpoint(), utxo))
-            .collect::<HashMap<_, _>>();
-
-        // add metadata for the inputs
-        for (psbt_input, input) in psbt.inputs.iter_mut().zip(psbt.unsigned_tx.input.iter()) {
-            let utxo = match lookup_output.remove(&input.previous_output) {
-                Some(utxo) => utxo,
-                None => continue,
-            };
-
-            match utxo {
-                Utxo::Local(utxo) => {
-                    *psbt_input =
-                        match self.get_psbt_input(utxo, params.sighash, params.only_witness_utxo) {
-                            Ok(psbt_input) => psbt_input,
-                            Err(e) => match e {
-                                CreateTxError::UnknownUtxo => psbt::Input {
-                                    sighash_type: params.sighash,
-                                    ..psbt::Input::default()
-                                },
-                                _ => return Err(e),
-                            },
-                        }
-                }
-                Utxo::Foreign {
-                    outpoint,
-                    psbt_input: foreign_psbt_input,
-                    ..
-                } => {
-                    let is_taproot = foreign_psbt_input
-                        .witness_utxo
-                        .as_ref()
-                        .map(|txout| txout.script_pubkey.is_p2tr())
-                        .unwrap_or(false);
-                    if !is_taproot
-                        && !params.only_witness_utxo
-                        && foreign_psbt_input.non_witness_utxo.is_none()
-                    {
-                        return Err(CreateTxError::MissingNonWitnessUtxo(outpoint));
-                    }
-                    *psbt_input = *foreign_psbt_input;
-                }
-            }
-        }
-
-        self.update_psbt_with_descriptor(&mut psbt)?;
-
-        Ok(psbt)
-    }
-
-    /// get the corresponding PSBT Input for a LocalUtxo
-    pub fn get_psbt_input(
-        &self,
-        utxo: LocalOutput,
-        sighash_type: Option<psbt::PsbtSighashType>,
-        only_witness_utxo: bool,
-    ) -> Result<psbt::Input, CreateTxError> {
-        // 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
-            .indexed_graph
-            .index
-            .index_of_spk(&utxo.txout.script_pubkey)
-            .ok_or(CreateTxError::UnknownUtxo)?;
-
-        let mut psbt_input = psbt::Input {
-            sighash_type,
-            ..psbt::Input::default()
-        };
-
-        let desc = self.get_descriptor_for_keychain(keychain);
-        let derived_descriptor = desc
-            .at_derivation_index(child)
-            .expect("child can't be hardened");
-
-        psbt_input
-            .update_with_descriptor_unchecked(&derived_descriptor)
-            .map_err(MiniscriptPsbtError::Conversion)?;
-
-        let prev_output = utxo.outpoint;
-        if let Some(prev_tx) = self.indexed_graph.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.as_ref().clone());
-            }
-        }
-        Ok(psbt_input)
-    }
-
-    fn update_psbt_with_descriptor(&self, psbt: &mut Psbt) -> Result<(), MiniscriptPsbtError> {
-        // We need to borrow `psbt` mutably within the loops, so we have to allocate a vec for all
-        // the input utxos and outputs
-        let utxos = (0..psbt.inputs.len())
-            .filter_map(|i| psbt.get_utxo_for(i).map(|utxo| (true, i, utxo)))
-            .chain(
-                psbt.unsigned_tx
-                    .output
-                    .iter()
-                    .enumerate()
-                    .map(|(i, out)| (false, i, out.clone())),
-            )
-            .collect::<Vec<_>>();
-
-        // 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.indexed_graph.index.index_of_spk(&out.script_pubkey)
-            {
-                let desc = self.get_descriptor_for_keychain(keychain);
-                let desc = desc
-                    .at_derivation_index(child)
-                    .expect("child can't be hardened");
-
-                if is_input {
-                    psbt.update_input_with_descriptor(index, &desc)
-                        .map_err(MiniscriptPsbtError::UtxoUpdate)?;
-                } else {
-                    psbt.update_output_with_descriptor(index, &desc)
-                        .map_err(MiniscriptPsbtError::OutputUpdate)?;
-                }
-            }
-        }
-
-        Ok(())
-    }
-
-    /// Return the checksum of the public descriptor associated to `keychain`
-    ///
-    /// Internally calls [`Self::get_descriptor_for_keychain`] to fetch the right descriptor
-    pub fn descriptor_checksum(&self, keychain: KeychainKind) -> String {
-        self.get_descriptor_for_keychain(keychain)
-            .to_string()
-            .split_once('#')
-            .unwrap()
-            .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: impl Into<Update>) -> Result<(), CannotConnectError> {
-        let update = update.into();
-        let mut changeset = match update.chain {
-            Some(chain_update) => ChangeSet::from(self.chain.apply_update(chain_update)?),
-            None => ChangeSet::default(),
-        };
-
-        let (_, index_changeset) = self
-            .indexed_graph
-            .index
-            .reveal_to_target_multi(&update.last_active_indices);
-        changeset.append(ChangeSet::from(indexed_tx_graph::ChangeSet::from(
-            index_changeset,
-        )));
-        changeset.append(ChangeSet::from(
-            self.indexed_graph.apply_update(update.graph),
-        ));
-        self.persist.stage(changeset);
-        Ok(())
-    }
-
-    /// Commits all currently [`staged`] changed to the persistence backend returning and error when
-    /// this fails.
-    ///
-    /// This returns whether the `update` resulted in any changes.
-    ///
-    /// [`staged`]: Self::staged
-    pub fn commit(&mut self) -> anyhow::Result<bool> {
-        self.persist.commit().map(|c| c.is_some())
-    }
-
-    /// Returns the changes that will be committed with the next call to [`commit`].
-    ///
-    /// [`commit`]: Self::commit
-    pub fn staged(&self) -> &ChangeSet {
-        self.persist.staged()
-    }
-
-    /// Get a reference to the inner [`TxGraph`].
-    pub fn tx_graph(&self) -> &TxGraph<ConfirmationTimeHeightAnchor> {
-        self.indexed_graph.graph()
-    }
-
-    /// Get a reference to the inner [`KeychainTxOutIndex`].
-    pub fn spk_index(&self) -> &KeychainTxOutIndex<KeychainKind> {
-        &self.indexed_graph.index
-    }
-
-    /// Get a reference to the inner [`LocalChain`].
-    pub fn local_chain(&self) -> &LocalChain {
-        &self.chain
-    }
-
-    /// Introduces a `block` of `height` to the wallet, and tries to connect it to the
-    /// `prev_blockhash` of the block's header.
-    ///
-    /// This is a convenience method that is equivalent to calling [`apply_block_connected_to`]
-    /// with `prev_blockhash` and `height-1` as the `connected_to` parameter.
-    ///
-    /// [`apply_block_connected_to`]: Self::apply_block_connected_to
-    pub fn apply_block(&mut self, block: &Block, height: u32) -> Result<(), CannotConnectError> {
-        let connected_to = match height.checked_sub(1) {
-            Some(prev_height) => BlockId {
-                height: prev_height,
-                hash: block.header.prev_blockhash,
-            },
-            None => BlockId {
-                height,
-                hash: block.block_hash(),
-            },
-        };
-        self.apply_block_connected_to(block, height, connected_to)
-            .map_err(|err| match err {
-                ApplyHeaderError::InconsistentBlocks => {
-                    unreachable!("connected_to is derived from the block so must be consistent")
-                }
-                ApplyHeaderError::CannotConnect(err) => err,
-            })
-    }
-
-    /// Applies relevant transactions from `block` of `height` to the wallet, and connects the
-    /// block to the internal chain.
-    ///
-    /// The `connected_to` parameter informs the wallet how this block connects to the internal
-    /// [`LocalChain`]. Relevant transactions are filtered from the `block` and inserted into the
-    /// internal [`TxGraph`].
-    pub fn apply_block_connected_to(
-        &mut self,
-        block: &Block,
-        height: u32,
-        connected_to: BlockId,
-    ) -> Result<(), ApplyHeaderError> {
-        let mut changeset = ChangeSet::default();
-        changeset.append(
-            self.chain
-                .apply_header_connected_to(&block.header, height, connected_to)?
-                .into(),
-        );
-        changeset.append(
-            self.indexed_graph
-                .apply_block_relevant(block, height)
-                .into(),
-        );
-        self.persist.stage(changeset);
-        Ok(())
-    }
-
-    /// Apply relevant unconfirmed transactions to the wallet.
-    ///
-    /// Transactions that are not relevant are filtered out.
-    ///
-    /// This method takes in an iterator of `(tx, last_seen)` where `last_seen` is the timestamp of
-    /// when the transaction was last seen in the mempool. This is used for conflict resolution
-    /// when there is conflicting unconfirmed transactions. The transaction with the later
-    /// `last_seen` is prioritized.
-    pub fn apply_unconfirmed_txs<'t>(
-        &mut self,
-        unconfirmed_txs: impl IntoIterator<Item = (&'t Transaction, u64)>,
-    ) {
-        let indexed_graph_changeset = self
-            .indexed_graph
-            .batch_insert_relevant_unconfirmed(unconfirmed_txs);
-        self.persist.stage(ChangeSet::from(indexed_graph_changeset));
-    }
-}
-
-/// Methods to construct sync/full-scan requests for spk-based chain sources.
-impl Wallet {
-    /// Create a partial [`SyncRequest`] for this wallet for all revealed spks.
-    ///
-    /// This is the first step when performing a spk-based wallet partial sync, the returned
-    /// [`SyncRequest`] collects all revealed script pubkeys from the wallet keychain needed to
-    /// start a blockchain sync with a spk based blockchain client.
-    pub fn start_sync_with_revealed_spks(&self) -> SyncRequest {
-        SyncRequest::from_chain_tip(self.chain.tip())
-            .cache_graph_txs(self.tx_graph())
-            .populate_with_revealed_spks(&self.indexed_graph.index, ..)
-    }
-
-    /// Create a [`FullScanRequest] for this wallet.
-    ///
-    /// This is the first step when performing a spk-based wallet full scan, the returned
-    /// [`FullScanRequest] collects iterators for the wallet's keychain script pub keys needed to
-    /// start a blockchain full scan with a spk based blockchain client.
-    ///
-    /// This operation is generally only used when importing or restoring a previously used wallet
-    /// in which the list of used scripts is not known.
-    pub fn start_full_scan(&self) -> FullScanRequest<KeychainKind> {
-        FullScanRequest::from_keychain_txout_index(self.chain.tip(), &self.indexed_graph.index)
-            .cache_graph_txs(self.tx_graph())
-    }
-}
-
-impl AsRef<bdk_chain::tx_graph::TxGraph<ConfirmationTimeHeightAnchor>> for Wallet {
-    fn as_ref(&self) -> &bdk_chain::tx_graph::TxGraph<ConfirmationTimeHeightAnchor> {
-        self.indexed_graph.graph()
-    }
-}
-
-/// Deterministically generate a unique name given the descriptors defining the wallet
-///
-/// Compatible with [`wallet_name_from_descriptor`]
-pub fn wallet_name_from_descriptor<T>(
-    descriptor: T,
-    change_descriptor: Option<T>,
-    network: Network,
-    secp: &SecpCtx,
-) -> Result<String, DescriptorError>
-where
-    T: IntoWalletDescriptor,
-{
-    //TODO check descriptors contains only public keys
-    let descriptor = descriptor
-        .into_wallet_descriptor(secp, network)?
-        .0
-        .to_string();
-    let mut wallet_name = calc_checksum(&descriptor[..descriptor.find('#').unwrap()])?;
-    if let Some(change_descriptor) = change_descriptor {
-        let change_descriptor = change_descriptor
-            .into_wallet_descriptor(secp, network)?
-            .0
-            .to_string();
-        wallet_name.push_str(
-            calc_checksum(&change_descriptor[..change_descriptor.find('#').unwrap()])?.as_str(),
-        );
-    }
-
-    Ok(wallet_name)
-}
-
-fn new_local_utxo(
-    keychain: KeychainKind,
-    derivation_index: u32,
-    full_txo: FullTxOut<ConfirmationTimeHeightAnchor>,
-) -> LocalOutput {
-    LocalOutput {
-        outpoint: full_txo.outpoint,
-        txout: full_txo.txout,
-        is_spent: full_txo.spent_by.is_some(),
-        confirmation_time: full_txo.chain_position.into(),
-        keychain,
-        derivation_index,
-    }
-}
-
-fn create_signers<E: IntoWalletDescriptor>(
-    index: &mut KeychainTxOutIndex<KeychainKind>,
-    secp: &Secp256k1<All>,
-    descriptor: E,
-    change_descriptor: Option<E>,
-    network: Network,
-) -> Result<(Arc<SignersContainer>, Arc<SignersContainer>), crate::descriptor::error::Error> {
-    let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, secp, network)?;
-    let signers = Arc::new(SignersContainer::build(keymap, &descriptor, secp));
-    let _ = index.insert_descriptor(KeychainKind::External, descriptor);
-
-    let change_signers = match change_descriptor {
-        Some(descriptor) => {
-            let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, secp, network)?;
-            let signers = Arc::new(SignersContainer::build(keymap, &descriptor, secp));
-            let _ = index.insert_descriptor(KeychainKind::Internal, descriptor);
-            signers
-        }
-        None => Arc::new(SignersContainer::new()),
-    };
-
-    Ok((signers, change_signers))
-}
-
-/// Transforms a [`FeeRate`] to `f64` with unit as sat/vb.
-#[macro_export]
-#[doc(hidden)]
-macro_rules! floating_rate {
-    ($rate:expr) => {{
-        use $crate::bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
-        // sat_kwu / 250.0 -> sat_vb
-        $rate.to_sat_per_kwu() as f64 / ((1000 / WITNESS_SCALE_FACTOR) as f64)
-    }};
-}
-
-#[macro_export]
-#[doc(hidden)]
-/// Macro for getting a wallet for use in a doctest
-macro_rules! doctest_wallet {
-    () => {{
-        use $crate::bitcoin::{BlockHash, Transaction, absolute, TxOut, Network, hashes::Hash};
-        use $crate::chain::{ConfirmationTime, BlockId};
-        use $crate::{KeychainKind, wallet::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,
-        )
-        .unwrap();
-        let address = wallet.peek_address(KeychainKind::External, 0).address;
-        let tx = Transaction {
-            version: transaction::Version::ONE,
-            lock_time: absolute::LockTime::ZERO,
-            input: vec![],
-            output: vec![TxOut {
-                value: Amount::from_sat(500_000),
-                script_pubkey: address.script_pubkey(),
-            }],
-        };
-        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
-        });
-
-        wallet
-    }}
-}
-
-
\ 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 deleted file mode 100644 index 1edcc8dd06..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/signer.rs.html +++ /dev/null @@ -1,2389 +0,0 @@ -signer.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
-1148
-1149
-1150
-1151
-1152
-1153
-1154
-1155
-1156
-1157
-1158
-1159
-1160
-1161
-1162
-1163
-1164
-1165
-1166
-1167
-1168
-1169
-1170
-1171
-1172
-1173
-1174
-1175
-1176
-1177
-1178
-1179
-1180
-1181
-1182
-1183
-1184
-1185
-1186
-1187
-1188
-1189
-1190
-1191
-1192
-1193
-
// 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.
-
-//! Generalized signers
-//!
-//! This module provides the ability to add customized signers to a [`Wallet`](super::Wallet)
-//! through the [`Wallet::add_signer`](super::Wallet::add_signer) function.
-//!
-//! ```
-//! # use alloc::sync::Arc;
-//! # use core::str::FromStr;
-//! # use bitcoin::secp256k1::{Secp256k1, All};
-//! # use bitcoin::*;
-//! # use bdk::signer::*;
-//! # use bdk::*;
-//! # #[derive(Debug)]
-//! # struct CustomHSM;
-//! # impl CustomHSM {
-//! #     fn hsm_sign_input(&self, _psbt: &mut Psbt, _input: usize) -> Result<(), SignerError> {
-//! #         Ok(())
-//! #     }
-//! #     fn connect() -> Self {
-//! #         CustomHSM
-//! #     }
-//! #     fn get_id(&self) -> SignerId {
-//! #         SignerId::Dummy(0)
-//! #     }
-//! # }
-//! #[derive(Debug)]
-//! struct CustomSigner {
-//!     device: CustomHSM,
-//! }
-//!
-//! impl CustomSigner {
-//!     fn connect() -> Self {
-//!         CustomSigner { device: CustomHSM::connect() }
-//!     }
-//! }
-//!
-//! impl SignerCommon for CustomSigner {
-//!     fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
-//!         self.device.get_id()
-//!     }
-//! }
-//!
-//! impl InputSigner for CustomSigner {
-//!     fn sign_input(
-//!         &self,
-//!         psbt: &mut Psbt,
-//!         input_index: usize,
-//!         _sign_options: &SignOptions,
-//!         _secp: &Secp256k1<All>,
-//!     ) -> Result<(), SignerError> {
-//!         self.device.hsm_sign_input(psbt, input_index)?;
-//!
-//!         Ok(())
-//!     }
-//! }
-//!
-//! let custom_signer = CustomSigner::connect();
-//!
-//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
-//! let mut wallet = Wallet::new_no_persist(descriptor, None, Network::Testnet)?;
-//! wallet.add_signer(
-//!     KeychainKind::External,
-//!     SignerOrdering(200),
-//!     Arc::new(custom_signer)
-//! );
-//!
-//! # Ok::<_, anyhow::Error>(())
-//! ```
-
-use crate::collections::BTreeMap;
-use alloc::string::String;
-use alloc::sync::Arc;
-use alloc::vec::Vec;
-use core::cmp::Ordering;
-use core::fmt;
-use core::ops::{Bound::Included, Deref};
-
-use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpriv};
-use bitcoin::hashes::hash160;
-use bitcoin::secp256k1::Message;
-use bitcoin::sighash::{EcdsaSighashType, TapSighash, TapSighashType};
-use bitcoin::{ecdsa, psbt, sighash, taproot};
-use bitcoin::{key::TapTweak, key::XOnlyPublicKey, secp256k1};
-use bitcoin::{PrivateKey, Psbt, PublicKey};
-
-use miniscript::descriptor::{
-    Descriptor, DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey,
-    InnerXKey, KeyMap, SinglePriv, SinglePubKey,
-};
-use miniscript::{Legacy, Segwitv0, SigType, Tap, ToPublicKey};
-
-use super::utils::SecpCtx;
-use crate::descriptor::{DescriptorMeta, XKeyUtils};
-use crate::psbt::PsbtUtils;
-use crate::wallet::error::MiniscriptPsbtError;
-
-/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
-/// multiple of them
-#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq, Hash)]
-pub enum SignerId {
-    /// Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA public key
-    PkHash(hash160::Hash),
-    /// The fingerprint of a BIP32 extended key
-    Fingerprint(Fingerprint),
-    /// Dummy identifier
-    Dummy(u64),
-}
-
-impl From<hash160::Hash> for SignerId {
-    fn from(hash: hash160::Hash) -> SignerId {
-        SignerId::PkHash(hash)
-    }
-}
-
-impl From<Fingerprint> for SignerId {
-    fn from(fing: Fingerprint) -> SignerId {
-        SignerId::Fingerprint(fing)
-    }
-}
-
-/// Signing error
-#[derive(Debug)]
-pub enum SignerError {
-    /// The private key is missing for the required public key
-    MissingKey,
-    /// The private key in use has the right fingerprint but derives differently than expected
-    InvalidKey,
-    /// The user canceled the operation
-    UserCanceled,
-    /// Input index is out of range
-    InputIndexOutOfRange,
-    /// The `non_witness_utxo` field of the transaction is required to sign this input
-    MissingNonWitnessUtxo,
-    /// The `non_witness_utxo` specified is invalid
-    InvalidNonWitnessUtxo,
-    /// The `witness_utxo` field of the transaction is required to sign this input
-    MissingWitnessUtxo,
-    /// The `witness_script` field of the transaction is required to sign this input
-    MissingWitnessScript,
-    /// The fingerprint and derivation path are missing from the psbt input
-    MissingHdKeypath,
-    /// The psbt contains a non-`SIGHASH_ALL` sighash in one of its input and the user hasn't
-    /// explicitly allowed them
-    ///
-    /// To enable signing transactions with non-standard sighashes set
-    /// [`SignOptions::allow_all_sighashes`] to `true`.
-    NonStandardSighash,
-    /// Invalid SIGHASH for the signing context in use
-    InvalidSighash,
-    /// Error while computing the hash to sign
-    SighashError(sighash::Error),
-    /// Miniscript PSBT error
-    MiniscriptPsbt(MiniscriptPsbtError),
-    /// To be used only by external libraries implementing [`InputSigner`] or
-    /// [`TransactionSigner`], so that they can return their own custom errors, without having to
-    /// modify [`SignerError`] in BDK.
-    External(String),
-}
-
-impl From<sighash::Error> for SignerError {
-    fn from(e: sighash::Error) -> Self {
-        SignerError::SighashError(e)
-    }
-}
-
-impl fmt::Display for SignerError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::MissingKey => write!(f, "Missing private key"),
-            Self::InvalidKey => write!(f, "The private key in use has the right fingerprint but derives differently than expected"),
-            Self::UserCanceled => write!(f, "The user canceled the operation"),
-            Self::InputIndexOutOfRange => write!(f, "Input index out of range"),
-            Self::MissingNonWitnessUtxo => write!(f, "Missing non-witness UTXO"),
-            Self::InvalidNonWitnessUtxo => write!(f, "Invalid non-witness UTXO"),
-            Self::MissingWitnessUtxo => write!(f, "Missing witness UTXO"),
-            Self::MissingWitnessScript => write!(f, "Missing witness script"),
-            Self::MissingHdKeypath => write!(f, "Missing fingerprint and derivation path"),
-            Self::NonStandardSighash => write!(f, "The psbt contains a non standard sighash"),
-            Self::InvalidSighash => write!(f, "Invalid SIGHASH for the signing context in use"),
-            Self::SighashError(err) => write!(f, "Error while computing the hash to sign: {}", err),
-            Self::MiniscriptPsbt(err) => write!(f, "Miniscript PSBT error: {}", err),
-            Self::External(err) => write!(f, "{}", err),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for SignerError {}
-
-/// Signing context
-///
-/// Used by our software signers to determine the type of signatures to make
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum SignerContext {
-    /// Legacy context
-    Legacy,
-    /// Segwit v0 context (BIP 143)
-    Segwitv0,
-    /// Taproot context (BIP 340)
-    Tap {
-        /// Whether the signer can sign for the internal key or not
-        is_internal_key: bool,
-    },
-}
-
-/// Wrapper to pair a signer with its context
-#[derive(Debug, Clone)]
-pub struct SignerWrapper<S: Sized + fmt::Debug + Clone> {
-    signer: S,
-    ctx: SignerContext,
-}
-
-impl<S: Sized + fmt::Debug + Clone> SignerWrapper<S> {
-    /// Create a wrapped signer from a signer and a context
-    pub fn new(signer: S, ctx: SignerContext) -> Self {
-        SignerWrapper { signer, ctx }
-    }
-}
-
-impl<S: Sized + fmt::Debug + Clone> Deref for SignerWrapper<S> {
-    type Target = S;
-
-    fn deref(&self) -> &Self::Target {
-        &self.signer
-    }
-}
-
-/// Common signer methods
-pub trait SignerCommon: fmt::Debug + Send + Sync {
-    /// Return the [`SignerId`] for this signer
-    ///
-    /// The [`SignerId`] can be used to lookup a signer in the [`Wallet`](crate::Wallet)'s signers map or to
-    /// compare two signers.
-    fn id(&self, secp: &SecpCtx) -> SignerId;
-
-    /// 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).
-    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
-        None
-    }
-}
-
-/// 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`].
-pub trait InputSigner: SignerCommon {
-    /// Sign a single psbt input
-    fn sign_input(
-        &self,
-        psbt: &mut Psbt,
-        input_index: usize,
-        sign_options: &SignOptions,
-        secp: &SecpCtx,
-    ) -> Result<(), SignerError>;
-}
-
-/// PSBT signer
-///
-/// This trait can be implemented when the signer can't sign inputs individually, but signs the whole transaction
-/// at once.
-pub trait TransactionSigner: SignerCommon {
-    /// Sign all the inputs of the psbt
-    fn sign_transaction(
-        &self,
-        psbt: &mut Psbt,
-        sign_options: &SignOptions,
-        secp: &SecpCtx,
-    ) -> Result<(), SignerError>;
-}
-
-impl<T: InputSigner> TransactionSigner for T {
-    fn sign_transaction(
-        &self,
-        psbt: &mut Psbt,
-        sign_options: &SignOptions,
-        secp: &SecpCtx,
-    ) -> Result<(), SignerError> {
-        for input_index in 0..psbt.inputs.len() {
-            self.sign_input(psbt, input_index, sign_options, secp)?;
-        }
-
-        Ok(())
-    }
-}
-
-impl SignerCommon for SignerWrapper<DescriptorXKey<Xpriv>> {
-    fn id(&self, secp: &SecpCtx) -> SignerId {
-        SignerId::from(self.root_fingerprint(secp))
-    }
-
-    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
-        Some(DescriptorSecretKey::XPrv(self.signer.clone()))
-    }
-}
-
-impl InputSigner for SignerWrapper<DescriptorXKey<Xpriv>> {
-    fn sign_input(
-        &self,
-        psbt: &mut Psbt,
-        input_index: usize,
-        sign_options: &SignOptions,
-        secp: &SecpCtx,
-    ) -> Result<(), SignerError> {
-        if input_index >= psbt.inputs.len() {
-            return Err(SignerError::InputIndexOutOfRange);
-        }
-
-        if psbt.inputs[input_index].final_script_sig.is_some()
-            || psbt.inputs[input_index].final_script_witness.is_some()
-        {
-            return Ok(());
-        }
-
-        let tap_key_origins = psbt.inputs[input_index]
-            .tap_key_origins
-            .iter()
-            .map(|(pk, (_, keysource))| (SinglePubKey::XOnly(*pk), keysource));
-        let (public_key, full_path) = match psbt.inputs[input_index]
-            .bip32_derivation
-            .iter()
-            .map(|(pk, keysource)| (SinglePubKey::FullKey(PublicKey::new(*pk)), keysource))
-            .chain(tap_key_origins)
-            .find_map(|(pk, keysource)| {
-                if self.matches(keysource, secp).is_some() {
-                    Some((pk, keysource.1.clone()))
-                } else {
-                    None
-                }
-            }) {
-            Some((pk, full_path)) => (pk, full_path),
-            None => return Ok(()),
-        };
-
-        let derived_key = match self.origin.clone() {
-            Some((_fingerprint, origin_path)) => {
-                let deriv_path = DerivationPath::from(
-                    &full_path.into_iter().cloned().collect::<Vec<ChildNumber>>()
-                        [origin_path.len()..],
-                );
-                self.xkey.derive_priv(secp, &deriv_path).unwrap()
-            }
-            None => self.xkey.derive_priv(secp, &full_path).unwrap(),
-        };
-
-        let computed_pk = secp256k1::PublicKey::from_secret_key(secp, &derived_key.private_key);
-        let valid_key = match public_key {
-            SinglePubKey::FullKey(pk) if pk.inner == computed_pk => true,
-            SinglePubKey::XOnly(x_only) if XOnlyPublicKey::from(computed_pk) == x_only => true,
-            _ => false,
-        };
-        if !valid_key {
-            Err(SignerError::InvalidKey)
-        } else {
-            // HD wallets imply compressed keys
-            let priv_key = PrivateKey {
-                compressed: true,
-                network: self.xkey.network,
-                inner: derived_key.private_key,
-            };
-
-            SignerWrapper::new(priv_key, self.ctx).sign_input(psbt, input_index, sign_options, secp)
-        }
-    }
-}
-
-fn multikey_to_xkeys<K: InnerXKey + Clone>(
-    multikey: DescriptorMultiXKey<K>,
-) -> Vec<DescriptorXKey<K>> {
-    multikey
-        .derivation_paths
-        .into_paths()
-        .into_iter()
-        .map(|derivation_path| DescriptorXKey {
-            origin: multikey.origin.clone(),
-            xkey: multikey.xkey.clone(),
-            derivation_path,
-            wildcard: multikey.wildcard,
-        })
-        .collect()
-}
-
-impl SignerCommon for SignerWrapper<DescriptorMultiXKey<Xpriv>> {
-    fn id(&self, secp: &SecpCtx) -> SignerId {
-        SignerId::from(self.root_fingerprint(secp))
-    }
-
-    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
-        Some(DescriptorSecretKey::MultiXPrv(self.signer.clone()))
-    }
-}
-
-impl InputSigner for SignerWrapper<DescriptorMultiXKey<Xpriv>> {
-    fn sign_input(
-        &self,
-        psbt: &mut Psbt,
-        input_index: usize,
-        sign_options: &SignOptions,
-        secp: &SecpCtx,
-    ) -> Result<(), SignerError> {
-        let xkeys = multikey_to_xkeys(self.signer.clone());
-        for xkey in xkeys {
-            SignerWrapper::new(xkey, self.ctx).sign_input(psbt, input_index, sign_options, secp)?
-        }
-        Ok(())
-    }
-}
-
-impl SignerCommon for SignerWrapper<PrivateKey> {
-    fn id(&self, secp: &SecpCtx) -> SignerId {
-        SignerId::from(self.public_key(secp).to_pubkeyhash(SigType::Ecdsa))
-    }
-
-    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
-        Some(DescriptorSecretKey::Single(SinglePriv {
-            key: self.signer,
-            origin: None,
-        }))
-    }
-}
-
-impl InputSigner for SignerWrapper<PrivateKey> {
-    fn sign_input(
-        &self,
-        psbt: &mut Psbt,
-        input_index: usize,
-        sign_options: &SignOptions,
-        secp: &SecpCtx,
-    ) -> Result<(), SignerError> {
-        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
-            return Err(SignerError::InputIndexOutOfRange);
-        }
-
-        if psbt.inputs[input_index].final_script_sig.is_some()
-            || psbt.inputs[input_index].final_script_witness.is_some()
-        {
-            return Ok(());
-        }
-
-        let pubkey = PublicKey::from_private_key(secp, self);
-        let x_only_pubkey = XOnlyPublicKey::from(pubkey.inner);
-
-        if let SignerContext::Tap { is_internal_key } = self.ctx {
-            if let Some(psbt_internal_key) = psbt.inputs[input_index].tap_internal_key {
-                if is_internal_key
-                    && psbt.inputs[input_index].tap_key_sig.is_none()
-                    && sign_options.sign_with_tap_internal_key
-                    && x_only_pubkey == psbt_internal_key
-                {
-                    let (hash, hash_ty) = Tap::sighash(psbt, input_index, None)?;
-                    sign_psbt_schnorr(
-                        &self.inner,
-                        x_only_pubkey,
-                        None,
-                        &mut psbt.inputs[input_index],
-                        hash,
-                        hash_ty,
-                        secp,
-                    );
-                }
-            }
-
-            if let Some((leaf_hashes, _)) =
-                psbt.inputs[input_index].tap_key_origins.get(&x_only_pubkey)
-            {
-                let leaf_hashes = leaf_hashes
-                    .iter()
-                    .filter(|lh| {
-                        // Removing the leaves we shouldn't sign for
-                        let should_sign = match &sign_options.tap_leaves_options {
-                            TapLeavesOptions::All => true,
-                            TapLeavesOptions::Include(v) => v.contains(lh),
-                            TapLeavesOptions::Exclude(v) => !v.contains(lh),
-                            TapLeavesOptions::None => false,
-                        };
-                        // Filtering out the leaves without our key
-                        should_sign
-                            && !psbt.inputs[input_index]
-                                .tap_script_sigs
-                                .contains_key(&(x_only_pubkey, **lh))
-                    })
-                    .cloned()
-                    .collect::<Vec<_>>();
-                for lh in leaf_hashes {
-                    let (hash, hash_ty) = Tap::sighash(psbt, input_index, Some(lh))?;
-                    sign_psbt_schnorr(
-                        &self.inner,
-                        x_only_pubkey,
-                        Some(lh),
-                        &mut psbt.inputs[input_index],
-                        hash,
-                        hash_ty,
-                        secp,
-                    );
-                }
-            }
-
-            return Ok(());
-        }
-
-        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
-            return Ok(());
-        }
-
-        let (hash, hash_ty) = match self.ctx {
-            SignerContext::Segwitv0 => {
-                let (h, t) = Segwitv0::sighash(psbt, input_index, ())?;
-                let h = h.to_raw_hash();
-                (h, t)
-            }
-            SignerContext::Legacy => {
-                let (h, t) = Legacy::sighash(psbt, input_index, ())?;
-                let h = h.to_raw_hash();
-                (h, t)
-            }
-            _ => return Ok(()), // handled above
-        };
-        sign_psbt_ecdsa(
-            &self.inner,
-            pubkey,
-            &mut psbt.inputs[input_index],
-            hash,
-            hash_ty,
-            secp,
-            sign_options.allow_grinding,
-        );
-
-        Ok(())
-    }
-}
-
-fn sign_psbt_ecdsa(
-    secret_key: &secp256k1::SecretKey,
-    pubkey: PublicKey,
-    psbt_input: &mut psbt::Input,
-    hash: impl bitcoin::hashes::Hash + bitcoin::secp256k1::ThirtyTwoByteHash,
-    hash_ty: EcdsaSighashType,
-    secp: &SecpCtx,
-    allow_grinding: bool,
-) {
-    let msg = &Message::from(hash);
-    let sig = if allow_grinding {
-        secp.sign_ecdsa_low_r(msg, secret_key)
-    } else {
-        secp.sign_ecdsa(msg, secret_key)
-    };
-    secp.verify_ecdsa(msg, &sig, &pubkey.inner)
-        .expect("invalid or corrupted ecdsa signature");
-
-    let final_signature = ecdsa::Signature { sig, hash_ty };
-    psbt_input.partial_sigs.insert(pubkey, final_signature);
-}
-
-// Calling this with `leaf_hash` = `None` will sign for key-spend
-fn sign_psbt_schnorr(
-    secret_key: &secp256k1::SecretKey,
-    pubkey: XOnlyPublicKey,
-    leaf_hash: Option<taproot::TapLeafHash>,
-    psbt_input: &mut psbt::Input,
-    hash: TapSighash,
-    hash_ty: TapSighashType,
-    secp: &SecpCtx,
-) {
-    let keypair = secp256k1::Keypair::from_seckey_slice(secp, secret_key.as_ref()).unwrap();
-    let keypair = match leaf_hash {
-        None => keypair
-            .tap_tweak(secp, psbt_input.tap_merkle_root)
-            .to_inner(),
-        Some(_) => keypair, // no tweak for script spend
-    };
-
-    let msg = &Message::from(hash);
-    let sig = secp.sign_schnorr(msg, &keypair);
-    secp.verify_schnorr(&sig, msg, &XOnlyPublicKey::from_keypair(&keypair).0)
-        .expect("invalid or corrupted schnorr signature");
-
-    let final_signature = taproot::Signature { sig, hash_ty };
-
-    if let Some(lh) = leaf_hash {
-        psbt_input
-            .tap_script_sigs
-            .insert((pubkey, lh), final_signature);
-    } else {
-        psbt_input.tap_key_sig = Some(final_signature);
-    }
-}
-
-/// 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.
-#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
-pub struct SignerOrdering(pub usize);
-
-impl Default for SignerOrdering {
-    fn default() -> Self {
-        SignerOrdering(100)
-    }
-}
-
-#[derive(Debug, Clone)]
-struct SignersContainerKey {
-    id: SignerId,
-    ordering: SignerOrdering,
-}
-
-impl From<(SignerId, SignerOrdering)> for SignersContainerKey {
-    fn from(tuple: (SignerId, SignerOrdering)) -> Self {
-        SignersContainerKey {
-            id: tuple.0,
-            ordering: tuple.1,
-        }
-    }
-}
-
-/// Container for multiple signers
-#[derive(Debug, Default, Clone)]
-pub struct SignersContainer(BTreeMap<SignersContainerKey, Arc<dyn TransactionSigner>>);
-
-impl SignersContainer {
-    /// Create a map of public keys to secret keys
-    pub fn as_key_map(&self, secp: &SecpCtx) -> KeyMap {
-        self.0
-            .values()
-            .filter_map(|signer| signer.descriptor_secret_key())
-            .filter_map(|secret| secret.to_public(secp).ok().map(|public| (public, secret)))
-            .collect()
-    }
-
-    /// Build a new signer container from a [`KeyMap`]
-    ///
-    /// Also looks at the corresponding descriptor to determine the [`SignerContext`] to attach to
-    /// the signers
-    pub fn build(
-        keymap: KeyMap,
-        descriptor: &Descriptor<DescriptorPublicKey>,
-        secp: &SecpCtx,
-    ) -> SignersContainer {
-        let mut container = SignersContainer::new();
-
-        for (pubkey, secret) in keymap {
-            let ctx = match descriptor {
-                Descriptor::Tr(tr) => SignerContext::Tap {
-                    is_internal_key: tr.internal_key() == &pubkey,
-                },
-                _ if descriptor.is_witness() => SignerContext::Segwitv0,
-                _ => SignerContext::Legacy,
-            };
-
-            match secret {
-                DescriptorSecretKey::Single(private_key) => container.add_external(
-                    SignerId::from(
-                        private_key
-                            .key
-                            .public_key(secp)
-                            .to_pubkeyhash(SigType::Ecdsa),
-                    ),
-                    SignerOrdering::default(),
-                    Arc::new(SignerWrapper::new(private_key.key, ctx)),
-                ),
-                DescriptorSecretKey::XPrv(xprv) => container.add_external(
-                    SignerId::from(xprv.root_fingerprint(secp)),
-                    SignerOrdering::default(),
-                    Arc::new(SignerWrapper::new(xprv, ctx)),
-                ),
-                DescriptorSecretKey::MultiXPrv(xprv) => container.add_external(
-                    SignerId::from(xprv.root_fingerprint(secp)),
-                    SignerOrdering::default(),
-                    Arc::new(SignerWrapper::new(xprv, ctx)),
-                ),
-            };
-        }
-
-        container
-    }
-}
-
-impl SignersContainer {
-    /// Default constructor
-    pub fn new() -> Self {
-        SignersContainer(Default::default())
-    }
-
-    /// Adds an external signer to the container for the specified id. Optionally returns the
-    /// signer that was previously in the container, if any
-    pub fn add_external(
-        &mut self,
-        id: SignerId,
-        ordering: SignerOrdering,
-        signer: Arc<dyn TransactionSigner>,
-    ) -> Option<Arc<dyn TransactionSigner>> {
-        self.0.insert((id, ordering).into(), signer)
-    }
-
-    /// Removes a signer from the container and returns it
-    pub fn remove(
-        &mut self,
-        id: SignerId,
-        ordering: SignerOrdering,
-    ) -> Option<Arc<dyn TransactionSigner>> {
-        self.0.remove(&(id, ordering).into())
-    }
-
-    /// Returns the list of identifiers of all the signers in the container
-    pub fn ids(&self) -> Vec<&SignerId> {
-        self.0
-            .keys()
-            .map(|SignersContainerKey { id, .. }| id)
-            .collect()
-    }
-
-    /// Returns the list of signers in the container, sorted by lowest to highest `ordering`
-    pub fn signers(&self) -> Vec<&Arc<dyn TransactionSigner>> {
-        self.0.values().collect()
-    }
-
-    /// Finds the signer with lowest ordering for a given id in the container.
-    pub fn find(&self, id: SignerId) -> Option<&Arc<dyn TransactionSigner>> {
-        self.0
-            .range((
-                Included(&(id.clone(), SignerOrdering(0)).into()),
-                Included(&(id.clone(), SignerOrdering(usize::MAX)).into()),
-            ))
-            .filter(|(k, _)| k.id == id)
-            .map(|(_, v)| v)
-            .next()
-    }
-}
-
-/// Options for a software signer
-///
-/// Adjust the behavior of our software signers and the way a transaction is finalized
-#[derive(Debug, Clone)]
-pub struct SignOptions {
-    /// Whether the signer should trust the `witness_utxo`, if the `non_witness_utxo` hasn't been
-    /// provided
-    ///
-    /// Defaults to `false` to mitigate the "SegWit bug" which should trick the wallet into
-    /// paying a fee larger than expected.
-    ///
-    /// Some wallets, especially if relatively old, might not provide the `non_witness_utxo` for
-    /// SegWit transactions in the PSBT they generate: in those cases setting this to `true`
-    /// should correctly produce a signature, at the expense of an increased trust in the creator
-    /// of the PSBT.
-    ///
-    /// For more details see: <https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd>
-    pub trust_witness_utxo: bool,
-
-    /// Whether the wallet should assume a specific height has been reached when trying to finalize
-    /// a transaction
-    ///
-    /// The wallet will only "use" a timelock to satisfy the spending policy of an input if the
-    /// timelock height has already been reached. This option allows overriding the "current height" to let the
-    /// wallet use timelocks in the future to spend a coin.
-    pub assume_height: Option<u32>,
-
-    /// Whether the signer should use the `sighash_type` set in the PSBT when signing, no matter
-    /// what its value is
-    ///
-    /// Defaults to `false` which will only allow signing using `SIGHASH_ALL`.
-    pub allow_all_sighashes: bool,
-
-    /// Whether to remove partial signatures from the PSBT inputs while finalizing PSBT.
-    ///
-    /// Defaults to `true` which will remove partial signatures during finalization.
-    pub remove_partial_sigs: bool,
-
-    /// Whether to remove taproot specific fields from the PSBT on finalization.
-    ///
-    /// For inputs this includes the taproot internal key, merkle root, and individual
-    /// scripts and signatures. For both inputs and outputs it includes key origin info.
-    ///
-    /// Defaults to `true` which will remove all of the above mentioned fields when finalizing.
-    ///
-    /// See [`BIP371`](https://github.com/bitcoin/bips/blob/master/bip-0371.mediawiki) for details.
-    pub remove_taproot_extras: bool,
-
-    /// Whether to try finalizing the PSBT after the inputs are signed.
-    ///
-    /// Defaults to `true` which will try finalizing PSBT after inputs are signed.
-    pub try_finalize: bool,
-
-    /// Specifies which Taproot script-spend leaves we should sign for. This option is
-    /// ignored if we're signing a non-taproot PSBT.
-    ///
-    /// Defaults to All, i.e., the wallet will sign all the leaves it has a key for.
-    pub tap_leaves_options: TapLeavesOptions,
-
-    /// Whether we should try to sign a taproot transaction with the taproot internal key
-    /// or not. This option is ignored if we're signing a non-taproot PSBT.
-    ///
-    /// Defaults to `true`, i.e., we always try to sign with the taproot internal key.
-    pub sign_with_tap_internal_key: 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.
-    pub allow_grinding: bool,
-}
-
-/// Customize which taproot script-path leaves the signer should sign.
-#[derive(Default, Debug, Clone, PartialEq, Eq)]
-pub enum TapLeavesOptions {
-    /// The signer will sign all the leaves it has a key for.
-    #[default]
-    All,
-    /// The signer won't sign leaves other than the ones specified. Note that it could still ignore
-    /// some of the specified leaves, if it doesn't have the right key to sign them.
-    Include(Vec<taproot::TapLeafHash>),
-    /// The signer won't sign the specified leaves.
-    Exclude(Vec<taproot::TapLeafHash>),
-    /// The signer won't sign any leaf.
-    None,
-}
-
-impl Default for SignOptions {
-    fn default() -> Self {
-        SignOptions {
-            trust_witness_utxo: false,
-            assume_height: None,
-            allow_all_sighashes: false,
-            remove_partial_sigs: true,
-            remove_taproot_extras: true,
-            try_finalize: true,
-            tap_leaves_options: TapLeavesOptions::default(),
-            sign_with_tap_internal_key: true,
-            allow_grinding: true,
-        }
-    }
-}
-
-pub(crate) trait ComputeSighash {
-    type Extra;
-    type Sighash;
-    type SighashType;
-
-    fn sighash(
-        psbt: &Psbt,
-        input_index: usize,
-        extra: Self::Extra,
-    ) -> Result<(Self::Sighash, Self::SighashType), SignerError>;
-}
-
-impl ComputeSighash for Legacy {
-    type Extra = ();
-    type Sighash = sighash::LegacySighash;
-    type SighashType = EcdsaSighashType;
-
-    fn sighash(
-        psbt: &Psbt,
-        input_index: usize,
-        _extra: (),
-    ) -> Result<(Self::Sighash, Self::SighashType), SignerError> {
-        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
-            return Err(SignerError::InputIndexOutOfRange);
-        }
-
-        let psbt_input = &psbt.inputs[input_index];
-        let tx_input = &psbt.unsigned_tx.input[input_index];
-
-        let sighash = psbt_input
-            .sighash_type
-            .unwrap_or_else(|| EcdsaSighashType::All.into())
-            .ecdsa_hash_ty()
-            .map_err(|_| SignerError::InvalidSighash)?;
-        let script = match psbt_input.redeem_script {
-            Some(ref redeem_script) => redeem_script.clone(),
-            None => {
-                let non_witness_utxo = psbt_input
-                    .non_witness_utxo
-                    .as_ref()
-                    .ok_or(SignerError::MissingNonWitnessUtxo)?;
-                let prev_out = non_witness_utxo
-                    .output
-                    .get(tx_input.previous_output.vout as usize)
-                    .ok_or(SignerError::InvalidNonWitnessUtxo)?;
-
-                prev_out.script_pubkey.clone()
-            }
-        };
-
-        Ok((
-            sighash::SighashCache::new(&psbt.unsigned_tx).legacy_signature_hash(
-                input_index,
-                &script,
-                sighash.to_u32(),
-            )?,
-            sighash,
-        ))
-    }
-}
-
-impl ComputeSighash for Segwitv0 {
-    type Extra = ();
-    type Sighash = sighash::SegwitV0Sighash;
-    type SighashType = EcdsaSighashType;
-
-    fn sighash(
-        psbt: &Psbt,
-        input_index: usize,
-        _extra: (),
-    ) -> Result<(Self::Sighash, Self::SighashType), SignerError> {
-        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
-            return Err(SignerError::InputIndexOutOfRange);
-        }
-
-        let psbt_input = &psbt.inputs[input_index];
-        let tx_input = &psbt.unsigned_tx.input[input_index];
-
-        let sighash_type = psbt_input
-            .sighash_type
-            .unwrap_or_else(|| EcdsaSighashType::All.into())
-            .ecdsa_hash_ty()
-            .map_err(|_| SignerError::InvalidSighash)?;
-
-        // Always try first with the non-witness utxo
-        let utxo = if let Some(prev_tx) = &psbt_input.non_witness_utxo {
-            // Check the provided prev-tx
-            if prev_tx.txid() != tx_input.previous_output.txid {
-                return Err(SignerError::InvalidNonWitnessUtxo);
-            }
-
-            // The output should be present, if it's missing the `non_witness_utxo` is invalid
-            prev_tx
-                .output
-                .get(tx_input.previous_output.vout as usize)
-                .ok_or(SignerError::InvalidNonWitnessUtxo)?
-        } else if let Some(witness_utxo) = &psbt_input.witness_utxo {
-            // Fallback to the witness_utxo. If we aren't allowed to use it, signing should fail
-            // before we get to this point
-            witness_utxo
-        } else {
-            // Nothing has been provided
-            return Err(SignerError::MissingNonWitnessUtxo);
-        };
-        let value = utxo.value;
-
-        let mut sighasher = sighash::SighashCache::new(&psbt.unsigned_tx);
-
-        let sighash = match psbt_input.witness_script {
-            Some(ref witness_script) => {
-                sighasher.p2wsh_signature_hash(input_index, witness_script, value, sighash_type)?
-            }
-            None => {
-                if utxo.script_pubkey.is_p2wpkh() {
-                    sighasher.p2wpkh_signature_hash(
-                        input_index,
-                        &utxo.script_pubkey,
-                        value,
-                        sighash_type,
-                    )?
-                } else if psbt_input
-                    .redeem_script
-                    .as_ref()
-                    .map(|s| s.is_p2wpkh())
-                    .unwrap_or(false)
-                {
-                    let script_pubkey = psbt_input.redeem_script.as_ref().unwrap();
-                    sighasher.p2wpkh_signature_hash(
-                        input_index,
-                        script_pubkey,
-                        value,
-                        sighash_type,
-                    )?
-                } else {
-                    return Err(SignerError::MissingWitnessScript);
-                }
-            }
-        };
-        Ok((sighash, sighash_type))
-    }
-}
-
-impl ComputeSighash for Tap {
-    type Extra = Option<taproot::TapLeafHash>;
-    type Sighash = TapSighash;
-    type SighashType = TapSighashType;
-
-    fn sighash(
-        psbt: &Psbt,
-        input_index: usize,
-        extra: Self::Extra,
-    ) -> Result<(Self::Sighash, TapSighashType), SignerError> {
-        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
-            return Err(SignerError::InputIndexOutOfRange);
-        }
-
-        let psbt_input = &psbt.inputs[input_index];
-
-        let sighash_type = psbt_input
-            .sighash_type
-            .unwrap_or_else(|| TapSighashType::Default.into())
-            .taproot_hash_ty()
-            .map_err(|_| SignerError::InvalidSighash)?;
-        let witness_utxos = (0..psbt.inputs.len())
-            .map(|i| psbt.get_utxo_for(i))
-            .collect::<Vec<_>>();
-        let mut all_witness_utxos = vec![];
-
-        let mut cache = sighash::SighashCache::new(&psbt.unsigned_tx);
-        let is_anyone_can_pay = psbt::PsbtSighashType::from(sighash_type).to_u32() & 0x80 != 0;
-        let prevouts = if is_anyone_can_pay {
-            sighash::Prevouts::One(
-                input_index,
-                witness_utxos[input_index]
-                    .as_ref()
-                    .ok_or(SignerError::MissingWitnessUtxo)?,
-            )
-        } else if witness_utxos.iter().all(Option::is_some) {
-            all_witness_utxos.extend(witness_utxos.iter().filter_map(|x| x.as_ref()));
-            sighash::Prevouts::All(&all_witness_utxos)
-        } else {
-            return Err(SignerError::MissingWitnessUtxo);
-        };
-
-        // Assume no OP_CODESEPARATOR
-        let extra = extra.map(|leaf_hash| (leaf_hash, 0xFFFFFFFF));
-
-        Ok((
-            cache.taproot_signature_hash(input_index, &prevouts, None, extra, sighash_type)?,
-            sighash_type,
-        ))
-    }
-}
-
-impl PartialOrd for SignersContainerKey {
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-
-impl Ord for SignersContainerKey {
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.ordering
-            .cmp(&other.ordering)
-            .then(self.id.cmp(&other.id))
-    }
-}
-
-impl PartialEq for SignersContainerKey {
-    fn eq(&self, other: &Self) -> bool {
-        self.id == other.id && self.ordering == other.ordering
-    }
-}
-
-impl Eq for SignersContainerKey {}
-
-#[cfg(test)]
-mod signers_container_tests {
-    use super::*;
-    use crate::descriptor;
-    use crate::descriptor::IntoWalletDescriptor;
-    use crate::keys::{DescriptorKey, IntoDescriptorKey};
-    use assert_matches::assert_matches;
-    use bitcoin::bip32;
-    use bitcoin::secp256k1::{All, Secp256k1};
-    use bitcoin::Network;
-    use core::str::FromStr;
-    use miniscript::ScriptContext;
-
-    fn is_equal(this: &Arc<dyn TransactionSigner>, that: &Arc<DummySigner>) -> bool {
-        let secp = Secp256k1::new();
-        this.id(&secp) == that.id(&secp)
-    }
-
-    // Signers added with the same ordering (like `Ordering::default`) created from `KeyMap`
-    // should be preserved and not overwritten.
-    // This happens usually when a set of signers is created from a descriptor with private keys.
-    #[test]
-    fn signers_with_same_ordering() {
-        let secp = Secp256k1::new();
-
-        let (prvkey1, _, _) = setup_keys(TPRV0_STR);
-        let (prvkey2, _, _) = setup_keys(TPRV1_STR);
-        let desc = descriptor!(sh(multi(2, prvkey1, prvkey2))).unwrap();
-        let (wallet_desc, keymap) = desc
-            .into_wallet_descriptor(&secp, Network::Testnet)
-            .unwrap();
-
-        let signers = SignersContainer::build(keymap, &wallet_desc, &secp);
-        assert_eq!(signers.ids().len(), 2);
-
-        let signers = signers.signers();
-        assert_eq!(signers.len(), 2);
-    }
-
-    #[test]
-    fn signers_sorted_by_ordering() {
-        let mut signers = SignersContainer::new();
-        let signer1 = Arc::new(DummySigner { number: 1 });
-        let signer2 = Arc::new(DummySigner { number: 2 });
-        let signer3 = Arc::new(DummySigner { number: 3 });
-
-        // Mixed order insertions verifies we are not inserting at head or tail.
-        signers.add_external(SignerId::Dummy(2), SignerOrdering(2), signer2.clone());
-        signers.add_external(SignerId::Dummy(1), SignerOrdering(1), signer1.clone());
-        signers.add_external(SignerId::Dummy(3), SignerOrdering(3), signer3.clone());
-
-        // Check that signers are sorted from lowest to highest ordering
-        let signers = signers.signers();
-
-        assert!(is_equal(signers[0], &signer1));
-        assert!(is_equal(signers[1], &signer2));
-        assert!(is_equal(signers[2], &signer3));
-    }
-
-    #[test]
-    fn find_signer_by_id() {
-        let mut signers = SignersContainer::new();
-        let signer1 = Arc::new(DummySigner { number: 1 });
-        let signer2 = Arc::new(DummySigner { number: 2 });
-        let signer3 = Arc::new(DummySigner { number: 3 });
-        let signer4 = Arc::new(DummySigner { number: 3 }); // Same ID as `signer3` but will use lower ordering.
-
-        let id1 = SignerId::Dummy(1);
-        let id2 = SignerId::Dummy(2);
-        let id3 = SignerId::Dummy(3);
-        let id_nonexistent = SignerId::Dummy(999);
-
-        signers.add_external(id1.clone(), SignerOrdering(1), signer1.clone());
-        signers.add_external(id2.clone(), SignerOrdering(2), signer2.clone());
-        signers.add_external(id3.clone(), SignerOrdering(3), signer3.clone());
-
-        assert_matches!(signers.find(id1), Some(signer) if is_equal(signer, &signer1));
-        assert_matches!(signers.find(id2), Some(signer) if is_equal(signer, &signer2));
-        assert_matches!(signers.find(id3.clone()), Some(signer) if is_equal(signer, &signer3));
-
-        // The `signer4` has the same ID as `signer3` but lower ordering.
-        // It should be found by `id3` instead of `signer3`.
-        signers.add_external(id3.clone(), SignerOrdering(2), signer4.clone());
-        assert_matches!(signers.find(id3), Some(signer) if is_equal(signer, &signer4));
-
-        // Can't find anything with ID that doesn't exist
-        assert_matches!(signers.find(id_nonexistent), None);
-    }
-
-    #[derive(Debug, Clone, Copy)]
-    struct DummySigner {
-        number: u64,
-    }
-
-    impl SignerCommon for DummySigner {
-        fn id(&self, _secp: &SecpCtx) -> SignerId {
-            SignerId::Dummy(self.number)
-        }
-    }
-
-    impl TransactionSigner for DummySigner {
-        fn sign_transaction(
-            &self,
-            _psbt: &mut Psbt,
-            _sign_options: &SignOptions,
-            _secp: &SecpCtx,
-        ) -> Result<(), SignerError> {
-            Ok(())
-        }
-    }
-
-    const TPRV0_STR:&str = "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf";
-    const TPRV1_STR:&str = "tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N";
-
-    const PATH: &str = "m/44'/1'/0'/0";
-
-    fn setup_keys<Ctx: ScriptContext>(
-        tprv: &str,
-    ) -> (DescriptorKey<Ctx>, DescriptorKey<Ctx>, Fingerprint) {
-        let secp: Secp256k1<All> = Secp256k1::new();
-        let path = bip32::DerivationPath::from_str(PATH).unwrap();
-        let tprv = bip32::Xpriv::from_str(tprv).unwrap();
-        let tpub = bip32::Xpub::from_priv(&secp, &tprv);
-        let fingerprint = tprv.fingerprint(&secp);
-        let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap();
-        let pubkey = (tpub, path).into_descriptor_key().unwrap();
-
-        (prvkey, pubkey, fingerprint)
-    }
-}
-
-
\ 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 deleted file mode 100644 index 82b073b939..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html +++ /dev/null @@ -1,2169 +0,0 @@ -tx_builder.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
-
// 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.
-
-//! Transaction builder
-//!
-//! ## Example
-//!
-//! ```
-//! # use std::str::FromStr;
-//! # use bitcoin::*;
-//! # use bdk::*;
-//! # use bdk::wallet::ChangeSet;
-//! # use bdk::wallet::error::CreateTxError;
-//! # use bdk::wallet::tx_builder::CreateTx;
-//! # use bdk_persist::PersistBackend;
-//! # use anyhow::Error;
-//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
-//! # let mut wallet = doctest_wallet!();
-//! // create a TxBuilder from a wallet
-//! let mut tx_builder = wallet.build_tx();
-//!
-//! tx_builder
-//!     // Create a transaction with one output to `to_address` of 50_000 satoshi
-//!     .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
-//!     // With a custom fee rate of 5.0 satoshi/vbyte
-//!     .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
-//!     // Only spend non-change outputs
-//!     .do_not_spend_change()
-//!     // Turn on RBF signaling
-//!     .enable_rbf();
-//! let psbt = tx_builder.finish()?;
-//! # Ok::<(), anyhow::Error>(())
-//! ```
-
-use alloc::{boxed::Box, rc::Rc, string::String, vec::Vec};
-use core::cell::RefCell;
-use core::fmt;
-use core::marker::PhantomData;
-
-use bitcoin::psbt::{self, Psbt};
-use bitcoin::script::PushBytes;
-use bitcoin::{absolute, Amount, FeeRate, OutPoint, ScriptBuf, Sequence, Transaction, Txid};
-
-use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
-use super::{CreateTxError, Wallet};
-use crate::collections::{BTreeMap, HashSet};
-use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
-
-/// Context in which the [`TxBuilder`] is valid
-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).
-#[derive(Debug, Default, Clone)]
-pub struct CreateTx;
-impl TxBuilderContext for CreateTx {}
-
-/// Marker type to indicate the [`TxBuilder`] is being used to bump the fee of an existing transaction.
-#[derive(Debug, Default, Clone)]
-pub struct BumpFee;
-impl TxBuilderContext for BumpFee {}
-
-/// 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.
-///
-/// Each option setting method on `TxBuilder` takes and returns `&mut self` so you can chain calls
-/// as in the following example:
-///
-/// ```
-/// # use bdk::*;
-/// # use bdk::wallet::tx_builder::*;
-/// # use bitcoin::*;
-/// # use core::str::FromStr;
-/// # use bdk::wallet::ChangeSet;
-/// # use bdk::wallet::error::CreateTxError;
-/// # use bdk_persist::PersistBackend;
-/// # use anyhow::Error;
-/// # let mut wallet = doctest_wallet!();
-/// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
-/// # let addr2 = addr1.clone();
-/// // chaining
-/// let psbt1 = {
-///     let mut builder = wallet.build_tx();
-///     builder
-///         .ordering(TxOrdering::Untouched)
-///         .add_recipient(addr1.script_pubkey(), Amount::from_sat(50_000))
-///         .add_recipient(addr2.script_pubkey(), Amount::from_sat(50_000));
-///     builder.finish()?
-/// };
-///
-/// // non-chaining
-/// let psbt2 = {
-///     let mut builder = wallet.build_tx();
-///     builder.ordering(TxOrdering::Untouched);
-///     for addr in &[addr1, addr2] {
-///         builder.add_recipient(addr.script_pubkey(), Amount::from_sat(50_000));
-///     }
-///     builder.finish()?
-/// };
-///
-/// assert_eq!(psbt1.unsigned_tx.output[..2], psbt2.unsigned_tx.output[..2]);
-/// # Ok::<(), anyhow::Error>(())
-/// ```
-///
-/// 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](super::tx_builder)'s documentation;
-///
-/// [`build_tx`]: Wallet::build_tx
-/// [`build_fee_bump`]: Wallet::build_fee_bump
-/// [`finish`]: Self::finish
-/// [`coin_selection`]: Self::coin_selection
-#[derive(Debug)]
-pub struct TxBuilder<'a, Cs, Ctx> {
-    pub(crate) wallet: Rc<RefCell<&'a mut Wallet>>,
-    pub(crate) params: TxParams,
-    pub(crate) coin_selection: Cs,
-    pub(crate) phantom: PhantomData<Ctx>,
-}
-
-/// The parameters for transaction creation sans coin selection algorithm.
-//TODO: TxParams should eventually be exposed publicly.
-#[derive(Default, Debug, Clone)]
-pub(crate) struct TxParams {
-    pub(crate) recipients: Vec<(ScriptBuf, u64)>,
-    pub(crate) drain_wallet: bool,
-    pub(crate) drain_to: Option<ScriptBuf>,
-    pub(crate) fee_policy: Option<FeePolicy>,
-    pub(crate) internal_policy_path: Option<BTreeMap<String, Vec<usize>>>,
-    pub(crate) external_policy_path: Option<BTreeMap<String, Vec<usize>>>,
-    pub(crate) utxos: Vec<WeightedUtxo>,
-    pub(crate) unspendable: HashSet<OutPoint>,
-    pub(crate) manually_selected_only: bool,
-    pub(crate) sighash: Option<psbt::PsbtSighashType>,
-    pub(crate) ordering: TxOrdering,
-    pub(crate) locktime: Option<absolute::LockTime>,
-    pub(crate) rbf: Option<RbfValue>,
-    pub(crate) version: Option<Version>,
-    pub(crate) change_policy: ChangeSpendPolicy,
-    pub(crate) only_witness_utxo: bool,
-    pub(crate) add_global_xpubs: bool,
-    pub(crate) include_output_redeem_witness_script: bool,
-    pub(crate) bumping_fee: Option<PreviousFee>,
-    pub(crate) current_height: Option<absolute::LockTime>,
-    pub(crate) allow_dust: bool,
-}
-
-#[derive(Clone, Copy, Debug)]
-pub(crate) struct PreviousFee {
-    pub absolute: u64,
-    pub rate: FeeRate,
-}
-
-#[derive(Debug, Clone, Copy)]
-pub(crate) enum FeePolicy {
-    FeeRate(FeeRate),
-    FeeAmount(u64),
-}
-
-impl Default for FeePolicy {
-    fn default() -> Self {
-        FeePolicy::FeeRate(FeeRate::BROADCAST_MIN)
-    }
-}
-
-impl<'a, Cs: Clone, Ctx> Clone for TxBuilder<'a, Cs, Ctx> {
-    fn clone(&self) -> Self {
-        TxBuilder {
-            wallet: self.wallet.clone(),
-            params: self.params.clone(),
-            coin_selection: self.coin_selection.clone(),
-            phantom: PhantomData,
-        }
-    }
-}
-
-// methods supported by both contexts, for any CoinSelectionAlgorithm
-impl<'a, Cs, Ctx> TxBuilder<'a, Cs, Ctx> {
-    /// Set a custom fee rate.
-    ///
-    /// This method sets the mining fee paid by the transaction as a rate on its size.
-    /// This means that the total fee paid is equal to `fee_rate` times the size
-    /// of the transaction. Default is 1 sat/vB in accordance with Bitcoin Core's default
-    /// relay policy.
-    ///
-    /// Note that this is really a minimum feerate -- it's possible to
-    /// overshoot it slightly since adding a change output to drain the remaining
-    /// excess might not be viable.
-    pub fn fee_rate(&mut self, fee_rate: FeeRate) -> &mut Self {
-        self.params.fee_policy = Some(FeePolicy::FeeRate(fee_rate));
-        self
-    }
-
-    /// Set an absolute fee
-    /// The fee_absolute method refers to the absolute transaction fee in satoshis (sats).
-    /// If anyone sets both the fee_absolute method and the fee_rate method,
-    /// the FeePolicy enum will be set by whichever method was called last,
-    /// as the FeeRate and FeeAmount are mutually exclusive.
-    ///
-    /// Note that this is really a minimum absolute fee -- it's possible to
-    /// overshoot it slightly since adding a change output to drain the remaining
-    /// excess might not be viable.
-    pub fn fee_absolute(&mut self, fee_amount: u64) -> &mut Self {
-        self.params.fee_policy = Some(FeePolicy::FeeAmount(fee_amount));
-        self
-    }
-
-    /// 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`](crate::descriptor::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
-    /// [`SatisfiableItem::Thresh::items`](crate::descriptor::policy::SatisfiableItem::Thresh::items)).
-    ///
-    /// ## Example
-    ///
-    /// An example of when the policy path is needed is the following descriptor:
-    /// `wsh(thresh(2,pk(A),sj:and_v(v:pk(B),n:older(6)),snj:and_v(v:pk(C),after(630000))))`,
-    /// derived from the miniscript policy `thresh(2,pk(A),and(pk(B),older(6)),and(pk(C),after(630000)))`.
-    /// It declares three descriptor fragments, and at the top level it uses `thresh()` to
-    /// ensure that at least two of them are satisfied. The individual fragments are:
-    ///
-    /// 1. `pk(A)`
-    /// 2. `and(pk(B),older(6))`
-    /// 3. `and(pk(C),after(630000))`
-    ///
-    /// When those conditions are combined in pairs, it's clear that the transaction needs to be created
-    /// differently depending on how the user intends to satisfy the policy afterwards:
-    ///
-    /// * If fragments `1` and `2` are used, the transaction will need to use a specific
-    ///   `n_sequence` in order to spend an `OP_CSV` branch.
-    /// * If fragments `1` and `3` are used, the transaction will need to use a specific `locktime`
-    ///   in order to spend an `OP_CLTV` branch.
-    /// * If fragments `2` and `3` are used, the transaction will need both.
-    ///
-    /// When the spending policy is represented as a tree (see
-    /// [`Wallet::policies`](super::Wallet::policies)), every node
-    /// is assigned a unique identifier that can be used in the policy path to specify which of
-    /// the node's children the user intends to satisfy: for instance, assuming the `thresh()`
-    /// root node of this example has an id of `aabbccdd`, the policy path map would look like:
-    ///
-    /// `{ "aabbccdd" => [0, 1] }`
-    ///
-    /// where the key is the node's id, and the value is a list of the children that should be
-    /// used, in no particular order.
-    ///
-    /// If a particularly complex descriptor has multiple ambiguous thresholds in its structure,
-    /// multiple entries can be added to the map, one for each node that requires an explicit path.
-    ///
-    /// ```
-    /// # use std::str::FromStr;
-    /// # use std::collections::BTreeMap;
-    /// # use bitcoin::*;
-    /// # use bdk::*;
-    /// # let to_address =
-    /// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
-    ///     .unwrap()
-    ///     .assume_checked();
-    /// # let mut wallet = doctest_wallet!();
-    /// let mut path = BTreeMap::new();
-    /// path.insert("aabbccdd".to_string(), vec![0, 1]);
-    ///
-    /// let builder = wallet
-    ///     .build_tx()
-    ///     .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
-    ///     .policy_path(path, KeychainKind::External);
-    ///
-    /// # Ok::<(), anyhow::Error>(())
-    /// ```
-    pub fn policy_path(
-        &mut self,
-        policy_path: BTreeMap<String, Vec<usize>>,
-        keychain: KeychainKind,
-    ) -> &mut Self {
-        let to_update = match keychain {
-            KeychainKind::Internal => &mut self.params.internal_policy_path,
-            KeychainKind::External => &mut self.params.external_policy_path,
-        };
-
-        *to_update = Some(policy_path);
-        self
-    }
-
-    /// 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.
-    pub fn add_utxos(&mut self, outpoints: &[OutPoint]) -> Result<&mut Self, AddUtxoError> {
-        {
-            let wallet = self.wallet.borrow();
-            let utxos = outpoints
-                .iter()
-                .map(|outpoint| {
-                    wallet
-                        .get_utxo(*outpoint)
-                        .ok_or(AddUtxoError::UnknownUtxo(*outpoint))
-                })
-                .collect::<Result<Vec<_>, _>>()?;
-
-            for utxo in utxos {
-                let descriptor = wallet.get_descriptor_for_keychain(utxo.keychain);
-                let satisfaction_weight = descriptor.max_weight_to_satisfy().unwrap();
-                self.params.utxos.push(WeightedUtxo {
-                    satisfaction_weight,
-                    utxo: Utxo::Local(utxo),
-                });
-            }
-        }
-
-        Ok(self)
-    }
-
-    /// 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.
-    pub fn add_utxo(&mut self, outpoint: OutPoint) -> Result<&mut Self, AddUtxoError> {
-        self.add_utxos(&[outpoint])
-    }
-
-    /// 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. `psbt_input`: To know the value.
-    /// 3. `satisfaction_weight`: To know how much weight/vbytes the input will add to the transaction for fee calculation.
-    ///
-    /// There are several security concerns about adding foreign UTXOs that application
-    /// developers should consider. First, how do you know the value of the input is correct? If a
-    /// `non_witness_utxo` is provided in the `psbt_input` then this method implicitly verifies the
-    /// value by checking it against the transaction. If only a `witness_utxo` is provided then this
-    /// method doesn't verify the value but just takes it as a given -- it is up to you to check
-    /// that whoever sent you the `input_psbt` was not lying!
-    ///
-    /// Secondly, you must somehow provide `satisfaction_weight` of the input. Depending on your
-    /// application it may be important that this be known precisely. If not, a malicious
-    /// counterparty may fool you into putting in a value that is too low, giving the transaction a
-    /// lower than expected feerate. They could also fool you into putting a value that is too high
-    /// causing you to pay a fee that is too high. The party who is broadcasting the transaction can
-    /// of course check the real input weight matches the expected weight prior to broadcasting.
-    ///
-    /// To guarantee the `max_weight_to_satisfy` is correct, you can require the party providing the
-    /// `psbt_input` provide a miniscript descriptor for the input so you can check it against the
-    /// `script_pubkey` and then ask it for the [`max_weight_to_satisfy`].
-    ///
-    /// This is an **EXPERIMENTAL** feature, API and other major changes are expected.
-    ///
-    /// In order to use [`Wallet::calculate_fee`] or [`Wallet::calculate_fee_rate`] for a transaction
-    /// created with foreign UTXO(s) you must manually insert the corresponding TxOut(s) into the tx
-    /// graph using the [`Wallet::insert_txout`] function.
-    ///
-    /// # Errors
-    ///
-    /// This method returns errors in the following circumstances:
-    ///
-    /// 1. The `psbt_input` does not contain a `witness_utxo` or `non_witness_utxo`.
-    /// 2. The data in `non_witness_utxo` does not match what is in `outpoint`.
-    ///
-    /// 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_witness_utxo`]: Self::only_witness_utxo
-    /// [`finish`]: Self::finish
-    /// [`max_weight_to_satisfy`]: miniscript::Descriptor::max_weight_to_satisfy
-    pub fn add_foreign_utxo(
-        &mut self,
-        outpoint: OutPoint,
-        psbt_input: psbt::Input,
-        satisfaction_weight: usize,
-    ) -> Result<&mut Self, AddForeignUtxoError> {
-        self.add_foreign_utxo_with_sequence(
-            outpoint,
-            psbt_input,
-            satisfaction_weight,
-            Sequence::MAX,
-        )
-    }
-
-    /// Same as [add_foreign_utxo](TxBuilder::add_foreign_utxo) but allows to set the nSequence value.
-    pub fn add_foreign_utxo_with_sequence(
-        &mut self,
-        outpoint: OutPoint,
-        psbt_input: psbt::Input,
-        satisfaction_weight: usize,
-        sequence: Sequence,
-    ) -> Result<&mut Self, AddForeignUtxoError> {
-        if psbt_input.witness_utxo.is_none() {
-            match psbt_input.non_witness_utxo.as_ref() {
-                Some(tx) => {
-                    if tx.txid() != outpoint.txid {
-                        return Err(AddForeignUtxoError::InvalidTxid {
-                            input_txid: tx.txid(),
-                            foreign_utxo: outpoint,
-                        });
-                    }
-                    if tx.output.len() <= outpoint.vout as usize {
-                        return Err(AddForeignUtxoError::InvalidOutpoint(outpoint));
-                    }
-                }
-                None => {
-                    return Err(AddForeignUtxoError::MissingUtxo);
-                }
-            }
-        }
-
-        self.params.utxos.push(WeightedUtxo {
-            satisfaction_weight,
-            utxo: Utxo::Foreign {
-                outpoint,
-                sequence: Some(sequence),
-                psbt_input: Box::new(psbt_input),
-            },
-        });
-
-        Ok(self)
-    }
-
-    /// 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.
-    ///
-    /// [`add_utxo`]: Self::add_utxo
-    pub fn manually_selected_only(&mut self) -> &mut Self {
-        self.params.manually_selected_only = true;
-        self
-    }
-
-    /// 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.
-    pub fn unspendable(&mut self, unspendable: Vec<OutPoint>) -> &mut Self {
-        self.params.unspendable = unspendable.into_iter().collect();
-        self
-    }
-
-    /// 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.
-    pub fn add_unspendable(&mut self, unspendable: OutPoint) -> &mut Self {
-        self.params.unspendable.insert(unspendable);
-        self
-    }
-
-    /// Sign with a specific sig hash
-    ///
-    /// **Use this option very carefully**
-    pub fn sighash(&mut self, sighash: psbt::PsbtSighashType) -> &mut Self {
-        self.params.sighash = Some(sighash);
-        self
-    }
-
-    /// Choose the ordering for inputs and outputs of the transaction
-    pub fn ordering(&mut self, ordering: TxOrdering) -> &mut Self {
-        self.params.ordering = ordering;
-        self
-    }
-
-    /// Use a specific nLockTime while creating the transaction
-    ///
-    /// This can cause conflicts if the wallet's descriptors contain an "after" (OP_CLTV) operator.
-    pub fn nlocktime(&mut self, locktime: absolute::LockTime) -> &mut Self {
-        self.params.locktime = Some(locktime);
-        self
-    }
-
-    /// 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.
-    pub fn version(&mut self, version: i32) -> &mut Self {
-        self.params.version = Some(Version(version));
-        self
-    }
-
-    /// Do not spend change outputs
-    ///
-    /// This effectively adds all the change outputs to the "unspendable" list. See
-    /// [`TxBuilder::unspendable`].
-    pub fn do_not_spend_change(&mut self) -> &mut Self {
-        self.params.change_policy = ChangeSpendPolicy::ChangeForbidden;
-        self
-    }
-
-    /// Only spend change outputs
-    ///
-    /// This effectively adds all the non-change outputs to the "unspendable" list. See
-    /// [`TxBuilder::unspendable`].
-    pub fn only_spend_change(&mut self) -> &mut Self {
-        self.params.change_policy = ChangeSpendPolicy::OnlyChange;
-        self
-    }
-
-    /// Set a specific [`ChangeSpendPolicy`]. See [`TxBuilder::do_not_spend_change`] and
-    /// [`TxBuilder::only_spend_change`] for some shortcuts.
-    pub fn change_policy(&mut self, change_policy: ChangeSpendPolicy) -> &mut Self {
-        self.params.change_policy = change_policy;
-        self
-    }
-
-    /// Only Fill-in the [`psbt::Input::witness_utxo`](bitcoin::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`.
-    pub fn only_witness_utxo(&mut self) -> &mut Self {
-        self.params.only_witness_utxo = true;
-        self
-    }
-
-    /// Fill-in the [`psbt::Output::redeem_script`](bitcoin::psbt::Output::redeem_script) and
-    /// [`psbt::Output::witness_script`](bitcoin::psbt::Output::witness_script) fields.
-    ///
-    /// This is useful for signers which always require it, like ColdCard hardware wallets.
-    pub fn include_output_redeem_witness_script(&mut self) -> &mut Self {
-        self.params.include_output_redeem_witness_script = true;
-        self
-    }
-
-    /// 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.
-    pub fn add_global_xpubs(&mut self) -> &mut Self {
-        self.params.add_global_xpubs = true;
-        self
-    }
-
-    /// Spend all the available inputs. This respects filters like [`TxBuilder::unspendable`] and the change policy.
-    pub fn drain_wallet(&mut self) -> &mut Self {
-        self.params.drain_wallet = true;
-        self
-    }
-
-    /// 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.
-    pub fn coin_selection<P: CoinSelectionAlgorithm>(
-        self,
-        coin_selection: P,
-    ) -> TxBuilder<'a, P, Ctx> {
-        TxBuilder {
-            wallet: self.wallet,
-            params: self.params,
-            coin_selection,
-            phantom: PhantomData,
-        }
-    }
-
-    /// Enable signaling RBF
-    ///
-    /// This will use the default nSequence value of `0xFFFFFFFD`.
-    pub fn enable_rbf(&mut self) -> &mut Self {
-        self.params.rbf = Some(RbfValue::Default);
-        self
-    }
-
-    /// 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.
-    pub fn enable_rbf_with_sequence(&mut self, nsequence: Sequence) -> &mut Self {
-        self.params.rbf = Some(RbfValue::Value(nsequence));
-        self
-    }
-
-    /// Set the current blockchain height.
-    ///
-    /// This will be used to:
-    /// 1. Set the nLockTime for preventing fee sniping.
-    /// **Note**: This will be ignored if you manually specify a nlocktime using [`TxBuilder::nlocktime`].
-    /// 2. Decide whether coinbase outputs are mature or not. If the coinbase outputs are not
-    ///    mature at `current_height`, we ignore them in the coin selection.
-    ///    If you want to create a transaction that spends immature coinbase inputs, manually
-    ///    add them using [`TxBuilder::add_utxos`].
-    ///
-    /// In both cases, if you don't provide a current height, we use the last sync height.
-    pub fn current_height(&mut self, height: u32) -> &mut Self {
-        self.params.current_height =
-            Some(absolute::LockTime::from_height(height).expect("Invalid height"));
-        self
-    }
-
-    /// 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.
-    pub fn allow_dust(&mut self, allow_dust: bool) -> &mut Self {
-        self.params.allow_dust = allow_dust;
-        self
-    }
-}
-
-impl<'a, Cs: CoinSelectionAlgorithm, Ctx> TxBuilder<'a, Cs, Ctx> {
-    /// Finish building the transaction.
-    ///
-    /// Returns a new [`Psbt`] per [`BIP174`].
-    ///
-    /// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
-    pub fn finish(self) -> Result<Psbt, CreateTxError> {
-        self.wallet
-            .borrow_mut()
-            .create_tx(self.coin_selection, self.params)
-    }
-}
-
-#[derive(Debug)]
-/// Error returned from [`TxBuilder::add_utxo`] and [`TxBuilder::add_utxos`]
-pub enum AddUtxoError {
-    /// Happens when trying to spend an UTXO that is not in the internal database
-    UnknownUtxo(OutPoint),
-}
-
-impl fmt::Display for AddUtxoError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::UnknownUtxo(outpoint) => write!(
-                f,
-                "UTXO not found in the internal database for txid: {} with vout: {}",
-                outpoint.txid, outpoint.vout
-            ),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for AddUtxoError {}
-
-#[derive(Debug)]
-/// Error returned from [`TxBuilder::add_foreign_utxo`].
-pub enum AddForeignUtxoError {
-    /// Foreign utxo outpoint txid does not match PSBT input txid
-    InvalidTxid {
-        /// PSBT input txid
-        input_txid: Txid,
-        /// Foreign UTXO outpoint
-        foreign_utxo: OutPoint,
-    },
-    /// Requested outpoint doesn't exist in the tx (vout greater than available outputs)
-    InvalidOutpoint(OutPoint),
-    /// Foreign utxo missing witness_utxo or non_witness_utxo
-    MissingUtxo,
-}
-
-impl fmt::Display for AddForeignUtxoError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::InvalidTxid {
-                input_txid,
-                foreign_utxo,
-            } => write!(
-                f,
-                "Foreign UTXO outpoint txid: {} does not match PSBT input txid: {}",
-                foreign_utxo.txid, input_txid,
-            ),
-            Self::InvalidOutpoint(outpoint) => write!(
-                f,
-                "Requested outpoint doesn't exist for txid: {} with vout: {}",
-                outpoint.txid, outpoint.vout,
-            ),
-            Self::MissingUtxo => write!(f, "Foreign utxo missing witness_utxo or non_witness_utxo"),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for AddForeignUtxoError {}
-
-#[derive(Debug)]
-/// Error returned from [`TxBuilder::allow_shrinking`]
-pub enum AllowShrinkingError {
-    /// Script/PubKey was not in the original transaction
-    MissingScriptPubKey(ScriptBuf),
-}
-
-impl fmt::Display for AllowShrinkingError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::MissingScriptPubKey(script_buf) => write!(
-                f,
-                "Script/PubKey was not in the original transaction: {}",
-                script_buf,
-            ),
-        }
-    }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for AllowShrinkingError {}
-
-impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs, CreateTx> {
-    /// Replace the recipients already added with a new list
-    pub fn set_recipients(&mut self, recipients: Vec<(ScriptBuf, Amount)>) -> &mut Self {
-        self.params.recipients = recipients
-            .into_iter()
-            .map(|(script, amount)| (script, amount.to_sat()))
-            .collect();
-        self
-    }
-
-    /// Add a recipient to the internal list
-    pub fn add_recipient(&mut self, script_pubkey: ScriptBuf, amount: Amount) -> &mut Self {
-        self.params
-            .recipients
-            .push((script_pubkey, amount.to_sat()));
-        self
-    }
-
-    /// Add data as an output, using OP_RETURN
-    pub fn add_data<T: AsRef<PushBytes>>(&mut self, data: &T) -> &mut Self {
-        let script = ScriptBuf::new_op_return(data);
-        self.add_recipient(script, Amount::ZERO);
-        self
-    }
-
-    /// 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
-    /// coins are too small) it will not be included in the resulting transaction. The only
-    /// difference is that it is valid to use `drain_to` without setting any ordinary recipients
-    /// with [`add_recipient`] (but it is perfectly fine to add recipients as well).
-    ///
-    /// If you choose not to set any recipients, you should either provide the utxos that the
-    /// transaction should spend via [`add_utxos`], or set [`drain_wallet`] to spend all of them.
-    ///
-    /// When bumping the fees of a transaction made with this option, you probably want to
-    /// use [`allow_shrinking`] to allow this output to be reduced to pay for the extra fees.
-    ///
-    /// # Example
-    ///
-    /// `drain_to` is very useful for draining all the coins in a wallet with [`drain_wallet`] to a
-    /// single address.
-    ///
-    /// ```
-    /// # use std::str::FromStr;
-    /// # use bitcoin::*;
-    /// # use bdk::*;
-    /// # use bdk::wallet::ChangeSet;
-    /// # use bdk::wallet::error::CreateTxError;
-    /// # use bdk::wallet::tx_builder::CreateTx;
-    /// # use bdk_persist::PersistBackend;
-    /// # use anyhow::Error;
-    /// # let to_address =
-    /// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
-    ///     .unwrap()
-    ///     .assume_checked();
-    /// # let mut wallet = doctest_wallet!();
-    /// let mut tx_builder = wallet.build_tx();
-    ///
-    /// tx_builder
-    ///     // Spend all outputs in this wallet.
-    ///     .drain_wallet()
-    ///     // Send the excess (which is all the coins minus the fee) to this address.
-    ///     .drain_to(to_address.script_pubkey())
-    ///     .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
-    ///     .enable_rbf();
-    /// let psbt = tx_builder.finish()?;
-    /// # Ok::<(), anyhow::Error>(())
-    /// ```
-    ///
-    /// [`allow_shrinking`]: Self::allow_shrinking
-    /// [`add_recipient`]: Self::add_recipient
-    /// [`add_utxos`]: Self::add_utxos
-    /// [`drain_wallet`]: Self::drain_wallet
-    pub fn drain_to(&mut self, script_pubkey: ScriptBuf) -> &mut Self {
-        self.params.drain_to = Some(script_pubkey);
-        self
-    }
-}
-
-// methods supported only by bump_fee
-impl<'a> TxBuilder<'a, 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.
-    ///
-    /// **Note** that the output may shrink to below the dust limit and therefore be removed. If it is
-    /// preserved then it is currently not guaranteed to be in the same position as it was
-    /// originally.
-    ///
-    /// Returns an `Err` if `script_pubkey` can't be found among the recipients of the
-    /// transaction we are bumping.
-    pub fn allow_shrinking(
-        &mut self,
-        script_pubkey: ScriptBuf,
-    ) -> Result<&mut Self, AllowShrinkingError> {
-        match self
-            .params
-            .recipients
-            .iter()
-            .position(|(recipient_script, _)| *recipient_script == script_pubkey)
-        {
-            Some(position) => {
-                self.params.recipients.remove(position);
-                self.params.drain_to = Some(script_pubkey);
-                Ok(self)
-            }
-            None => Err(AllowShrinkingError::MissingScriptPubKey(script_pubkey)),
-        }
-    }
-}
-
-/// Ordering of the transaction's inputs and outputs
-#[derive(Default, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
-pub enum TxOrdering {
-    /// Randomized (default)
-    #[default]
-    Shuffle,
-    /// Unchanged
-    Untouched,
-    /// BIP69 / Lexicographic
-    Bip69Lexicographic,
-}
-
-impl TxOrdering {
-    /// Sort transaction inputs and outputs by [`TxOrdering`] variant
-    pub fn sort_tx(&self, tx: &mut Transaction) {
-        match self {
-            TxOrdering::Untouched => {}
-            TxOrdering::Shuffle => {
-                use rand::seq::SliceRandom;
-                let mut rng = rand::thread_rng();
-                tx.input.shuffle(&mut rng);
-                tx.output.shuffle(&mut rng);
-            }
-            TxOrdering::Bip69Lexicographic => {
-                tx.input.sort_unstable_by_key(|txin| {
-                    (txin.previous_output.txid, txin.previous_output.vout)
-                });
-                tx.output
-                    .sort_unstable_by_key(|txout| (txout.value, txout.script_pubkey.clone()));
-            }
-        }
-    }
-}
-
-/// Transaction version
-///
-/// Has a default value of `1`
-#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
-pub(crate) struct Version(pub(crate) i32);
-
-impl Default for Version {
-    fn default() -> Self {
-        Version(1)
-    }
-}
-
-/// RBF nSequence value
-///
-/// Has a default value of `0xFFFFFFFD`
-#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
-pub(crate) enum RbfValue {
-    Default,
-    Value(Sequence),
-}
-
-impl RbfValue {
-    pub(crate) fn get_value(&self) -> Sequence {
-        match self {
-            RbfValue::Default => Sequence::ENABLE_RBF_NO_LOCKTIME,
-            RbfValue::Value(v) => *v,
-        }
-    }
-}
-
-/// Policy regarding the use of change outputs when creating a transaction
-#[derive(Default, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
-pub enum ChangeSpendPolicy {
-    /// Use both change and non-change outputs (default)
-    #[default]
-    ChangeAllowed,
-    /// Only use change outputs (see [`TxBuilder::only_spend_change`])
-    OnlyChange,
-    /// Only use non-change outputs (see [`TxBuilder::do_not_spend_change`])
-    ChangeForbidden,
-}
-
-impl ChangeSpendPolicy {
-    pub(crate) fn is_satisfied_by(&self, utxo: &LocalOutput) -> bool {
-        match self {
-            ChangeSpendPolicy::ChangeAllowed => true,
-            ChangeSpendPolicy::OnlyChange => utxo.keychain == KeychainKind::Internal,
-            ChangeSpendPolicy::ChangeForbidden => utxo.keychain == KeychainKind::External,
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    const ORDERING_TEST_TX: &str = "0200000003c26f3eb7932f7acddc5ddd26602b77e7516079b03090a16e2c2f54\
-                                    85d1fd600f0100000000ffffffffc26f3eb7932f7acddc5ddd26602b77e75160\
-                                    79b03090a16e2c2f5485d1fd600f0000000000ffffffff571fb3e02278217852\
-                                    dd5d299947e2b7354a639adc32ec1fa7b82cfb5dec530e0500000000ffffffff\
-                                    03e80300000000000002aaeee80300000000000001aa200300000000000001ff\
-                                    00000000";
-    macro_rules! ordering_test_tx {
-        () => {
-            deserialize::<bitcoin::Transaction>(&Vec::<u8>::from_hex(ORDERING_TEST_TX).unwrap())
-                .unwrap()
-        };
-    }
-
-    use bdk_chain::ConfirmationTime;
-    use bitcoin::consensus::deserialize;
-    use bitcoin::hex::FromHex;
-    use bitcoin::TxOut;
-
-    use super::*;
-
-    #[test]
-    fn test_output_ordering_default_shuffle() {
-        assert_eq!(TxOrdering::default(), TxOrdering::Shuffle);
-    }
-
-    #[test]
-    fn test_output_ordering_untouched() {
-        let original_tx = ordering_test_tx!();
-        let mut tx = original_tx.clone();
-
-        TxOrdering::Untouched.sort_tx(&mut tx);
-
-        assert_eq!(original_tx, tx);
-    }
-
-    #[test]
-    fn test_output_ordering_shuffle() {
-        let original_tx = ordering_test_tx!();
-        let mut tx = original_tx.clone();
-
-        (0..40)
-            .find(|_| {
-                TxOrdering::Shuffle.sort_tx(&mut tx);
-                original_tx.input != tx.input
-            })
-            .expect("it should have moved the inputs at least once");
-
-        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 core::str::FromStr;
-
-        let original_tx = ordering_test_tx!();
-        let mut tx = original_tx;
-
-        TxOrdering::Bip69Lexicographic.sort_tx(&mut tx);
-
-        assert_eq!(
-            tx.input[0].previous_output,
-            bitcoin::OutPoint::from_str(
-                "0e53ec5dfb2cb8a71fec32dc9a634a35b7e24799295ddd5278217822e0b31f57:5"
-            )
-            .unwrap()
-        );
-        assert_eq!(
-            tx.input[1].previous_output,
-            bitcoin::OutPoint::from_str(
-                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:0"
-            )
-            .unwrap()
-        );
-        assert_eq!(
-            tx.input[2].previous_output,
-            bitcoin::OutPoint::from_str(
-                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:1"
-            )
-            .unwrap()
-        );
-
-        assert_eq!(tx.output[0].value.to_sat(), 800);
-        assert_eq!(tx.output[1].script_pubkey, ScriptBuf::from(vec![0xAA]));
-        assert_eq!(
-            tx.output[2].script_pubkey,
-            ScriptBuf::from(vec![0xAA, 0xEE])
-        );
-    }
-
-    fn get_test_utxos() -> Vec<LocalOutput> {
-        use bitcoin::hashes::Hash;
-
-        vec![
-            LocalOutput {
-                outpoint: OutPoint {
-                    txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(),
-                    vout: 0,
-                },
-                txout: TxOut::NULL,
-                keychain: KeychainKind::External,
-                is_spent: false,
-                confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 },
-                derivation_index: 0,
-            },
-            LocalOutput {
-                outpoint: OutPoint {
-                    txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(),
-                    vout: 1,
-                },
-                txout: TxOut::NULL,
-                keychain: KeychainKind::Internal,
-                is_spent: false,
-                confirmation_time: ConfirmationTime::Confirmed {
-                    height: 32,
-                    time: 42,
-                },
-                derivation_index: 1,
-            },
-        ]
-    }
-
-    #[test]
-    fn test_change_spend_policy_default() {
-        let change_spend_policy = ChangeSpendPolicy::default();
-        let filtered = get_test_utxos()
-            .into_iter()
-            .filter(|u| change_spend_policy.is_satisfied_by(u))
-            .count();
-
-        assert_eq!(filtered, 2);
-    }
-
-    #[test]
-    fn test_change_spend_policy_no_internal() {
-        let change_spend_policy = ChangeSpendPolicy::ChangeForbidden;
-        let filtered = get_test_utxos()
-            .into_iter()
-            .filter(|u| change_spend_policy.is_satisfied_by(u))
-            .collect::<Vec<_>>();
-
-        assert_eq!(filtered.len(), 1);
-        assert_eq!(filtered[0].keychain, KeychainKind::External);
-    }
-
-    #[test]
-    fn test_change_spend_policy_only_internal() {
-        let change_spend_policy = ChangeSpendPolicy::OnlyChange;
-        let filtered = get_test_utxos()
-            .into_iter()
-            .filter(|u| change_spend_policy.is_satisfied_by(u))
-            .collect::<Vec<_>>();
-
-        assert_eq!(filtered.len(), 1);
-        assert_eq!(filtered[0].keychain, KeychainKind::Internal);
-    }
-
-    #[test]
-    fn test_default_tx_version_1() {
-        let version = Version::default();
-        assert_eq!(version.0, 1);
-    }
-}
-
-
\ No newline at end of file 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 deleted file mode 100644 index 214b43c052..0000000000 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/utils.rs.html +++ /dev/null @@ -1,373 +0,0 @@ -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
-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
-
// 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 bitcoin::secp256k1::{All, Secp256k1};
-use bitcoin::{absolute, Script, Sequence};
-
-use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
-
-/// 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
-// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
-// instead of a <= etc.
-pub trait IsDust {
-    /// Check whether or not a value is below dust limit
-    fn is_dust(&self, script: &Script) -> bool;
-}
-
-impl IsDust for u64 {
-    fn is_dust(&self, script: &Script) -> bool {
-        *self < script.dust_value().to_sat()
-    }
-}
-
-pub struct After {
-    pub current_height: Option<u32>,
-    pub assume_height_reached: bool,
-}
-
-impl After {
-    pub(crate) fn new(current_height: Option<u32>, assume_height_reached: bool) -> After {
-        After {
-            current_height,
-            assume_height_reached,
-        }
-    }
-}
-
-pub(crate) fn check_nsequence_rbf(rbf: Sequence, csv: Sequence) -> bool {
-    // The RBF value must enable relative timelocks
-    if !rbf.is_relative_lock_time() {
-        return false;
-    }
-
-    // Both values should be represented in the same unit (either time-based or
-    // block-height based)
-    if rbf.is_time_locked() != csv.is_time_locked() {
-        return false;
-    }
-
-    // The value should be at least `csv`
-    if rbf < csv {
-        return false;
-    }
-
-    true
-}
-
-impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for After {
-    fn check_after(&self, n: absolute::LockTime) -> bool {
-        if let Some(current_height) = self.current_height {
-            current_height >= n.to_consensus_u32()
-        } else {
-            self.assume_height_reached
-        }
-    }
-}
-
-pub struct Older {
-    pub current_height: Option<u32>,
-    pub create_height: Option<u32>,
-    pub assume_height_reached: bool,
-}
-
-impl Older {
-    pub(crate) fn new(
-        current_height: Option<u32>,
-        create_height: Option<u32>,
-        assume_height_reached: bool,
-    ) -> Older {
-        Older {
-            current_height,
-            create_height,
-            assume_height_reached,
-        }
-    }
-}
-
-impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for Older {
-    fn check_older(&self, n: Sequence) -> bool {
-        if let Some(current_height) = self.current_height {
-            // TODO: test >= / >
-            current_height
-                >= self
-                    .create_height
-                    .unwrap_or(0)
-                    .checked_add(n.to_consensus_u32())
-                    .expect("Overflowing addition")
-        } else {
-            self.assume_height_reached
-        }
-    }
-}
-
-pub(crate) type SecpCtx = Secp256k1<All>;
-
-#[cfg(test)]
-mod test {
-    // When nSequence is lower than this flag the timelock is interpreted as block-height-based,
-    // otherwise it's time-based
-    pub(crate) const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = 1 << 22;
-
-    use super::{check_nsequence_rbf, IsDust};
-    use crate::bitcoin::{Address, Network, Sequence};
-    use core::str::FromStr;
-
-    #[test]
-    fn test_is_dust() {
-        let script_p2pkh = Address::from_str("1GNgwA8JfG7Kc8akJ8opdNWJUihqUztfPe")
-            .unwrap()
-            .require_network(Network::Bitcoin)
-            .unwrap()
-            .script_pubkey();
-        assert!(script_p2pkh.is_p2pkh());
-        assert!(545.is_dust(&script_p2pkh));
-        assert!(!546.is_dust(&script_p2pkh));
-
-        let script_p2wpkh = Address::from_str("bc1qxlh2mnc0yqwas76gqq665qkggee5m98t8yskd8")
-            .unwrap()
-            .require_network(Network::Bitcoin)
-            .unwrap()
-            .script_pubkey();
-        assert!(script_p2wpkh.is_p2wpkh());
-        assert!(293.is_dust(&script_p2wpkh));
-        assert!(!294.is_dust(&script_p2wpkh));
-    }
-
-    #[test]
-    fn test_check_nsequence_rbf_msb_set() {
-        let result = check_nsequence_rbf(Sequence(0x80000000), Sequence(5000));
-        assert!(!result);
-    }
-
-    #[test]
-    fn test_check_nsequence_rbf_lt_csv() {
-        let result = check_nsequence_rbf(Sequence(4000), Sequence(5000));
-        assert!(!result);
-    }
-
-    #[test]
-    fn test_check_nsequence_rbf_different_unit() {
-        let result =
-            check_nsequence_rbf(Sequence(SEQUENCE_LOCKTIME_TYPE_FLAG + 5000), Sequence(5000));
-        assert!(!result);
-    }
-
-    #[test]
-    fn test_check_nsequence_rbf_mask() {
-        let result = check_nsequence_rbf(Sequence(0x3f + 10_000), Sequence(5000));
-        assert!(result);
-    }
-
-    #[test]
-    fn test_check_nsequence_rbf_same_unit_blocks() {
-        let result = check_nsequence_rbf(Sequence(10_000), Sequence(5000));
-        assert!(result);
-    }
-
-    #[test]
-    fn test_check_nsequence_rbf_same_unit_time() {
-        let result = check_nsequence_rbf(
-            Sequence(SEQUENCE_LOCKTIME_TYPE_FLAG + 10_000),
-            Sequence(SEQUENCE_LOCKTIME_TYPE_FLAG + 5000),
-        );
-        assert!(result);
-    }
-}
-
-
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_hwi/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_hwi/lib.rs.html index c22b6f92ce..12ec77af71 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_hwi/lib.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_hwi/lib.rs.html @@ -44,10 +44,10 @@ //! This crate contains HWISigner, an implementation of a [`TransactionSigner`] to be //! used with hardware wallets. //! ```no_run -//! # use bdk::bitcoin::Network; -//! # use bdk::signer::SignerOrdering; +//! # use bdk_wallet::bitcoin::Network; +//! # use bdk_wallet::signer::SignerOrdering; //! # use bdk_hwi::HWISigner; -//! # use bdk::{KeychainKind, SignOptions, Wallet}; +//! # use bdk_wallet::{KeychainKind, SignOptions, Wallet}; //! # use hwi::HWIClient; //! # use std::sync::Arc; //! # @@ -76,7 +76,7 @@ //! # } //! ``` //! -//! [`TransactionSigner`]: bdk::wallet::signer::TransactionSigner +//! [`TransactionSigner`]: bdk_wallet::wallet::signer::TransactionSigner mod signer; pub use signer::*; diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_hwi/signer.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_hwi/signer.rs.html index 53a032f206..2ce7b41795 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_hwi/signer.rs.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_hwi/signer.rs.html @@ -92,15 +92,15 @@ 92 93 94 -
use bdk::bitcoin::bip32::Fingerprint;
-use bdk::bitcoin::secp256k1::{All, Secp256k1};
-use bdk::bitcoin::Psbt;
+
use bdk_wallet::bitcoin::bip32::Fingerprint;
+use bdk_wallet::bitcoin::secp256k1::{All, Secp256k1};
+use bdk_wallet::bitcoin::Psbt;
 
 use hwi::error::Error;
 use hwi::types::{HWIChain, HWIDevice};
 use hwi::HWIClient;
 
-use bdk::signer::{SignerCommon, SignerError, SignerId, TransactionSigner};
+use bdk_wallet::signer::{SignerCommon, SignerError, SignerId, TransactionSigner};
 
 #[derive(Debug)]
 /// Custom signer for Hardware Wallets
@@ -132,7 +132,7 @@
     fn sign_transaction(
         &self,
         psbt: &mut Psbt,
-        _sign_options: &bdk::SignOptions,
+        _sign_options: &bdk_wallet::SignOptions,
         _secp: &Secp256k1<All>,
     ) -> Result<(), SignerError> {
         psbt.combine(
@@ -155,9 +155,9 @@
 //     fn test_hardware_signer() {
 //         use std::sync::Arc;
 //
-//         use bdk::tests::get_funded_wallet;
-//         use bdk::signer::SignerOrdering;
-//         use bdk::bitcoin::Network;
+//         use bdk_wallet::tests::get_funded_wallet;
+//         use bdk_wallet::signer::SignerOrdering;
+//         use bdk_wallet::bitcoin::Network;
 //         use crate::HWISigner;
 //         use hwi::HWIClient;
 //
@@ -172,12 +172,12 @@
 //
 //         let (mut wallet, _) = get_funded_wallet(&descriptors.internal[0]);
 //         wallet.add_signer(
-//             bdk::KeychainKind::External,
+//             bdk_wallet::KeychainKind::External,
 //             SignerOrdering(200),
 //             Arc::new(custom_signer),
 //         );
 //
-//         let addr = wallet.get_address(bdk::wallet::AddressIndex::LastUnused);
+//         let addr = wallet.get_address(bdk_wallet::wallet::AddressIndex::LastUnused);
 //         let mut builder = wallet.build_tx();
 //         builder.drain_to(addr.script_pubkey()).drain_wallet();
 //         let (mut psbt, _) = builder.finish().unwrap();
diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/checksum.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/checksum.rs.html
new file mode 100644
index 0000000000..8ca8881630
--- /dev/null
+++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/checksum.rs.html
@@ -0,0 +1,297 @@
+checksum.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
+
// 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.
+
+//! Descriptor checksum
+//!
+//! This module contains a re-implementation of the function used by Bitcoin Core to calculate the
+//! 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";
+
+fn poly_mod(mut c: u64, val: u64) -> u64 {
+    let c0 = c >> 35;
+    c = ((c & 0x7ffffffff) << 5) ^ val;
+    if c0 & 1 > 0 {
+        c ^= 0xf5dee51989
+    };
+    if c0 & 2 > 0 {
+        c ^= 0xa9fdca3312
+    };
+    if c0 & 4 > 0 {
+        c ^= 0x1bab10e32d
+    };
+    if c0 & 8 > 0 {
+        c ^= 0x3706b1677a
+    };
+    if c0 & 16 > 0 {
+        c ^= 0x644d626ffd
+    };
+
+    c
+}
+
+/// Compute the checksum bytes of a descriptor, excludes any existing checksum in the descriptor string from the calculation
+pub fn calc_checksum_bytes(mut desc: &str) -> Result<[u8; 8], DescriptorError> {
+    let mut c = 1;
+    let mut cls = 0;
+    let mut clscount = 0;
+
+    let mut original_checksum = None;
+    if let Some(split) = desc.split_once('#') {
+        desc = split.0;
+        original_checksum = Some(split.1);
+    }
+
+    for ch in desc.as_bytes() {
+        let pos = INPUT_CHARSET
+            .iter()
+            .position(|b| b == ch)
+            .ok_or(DescriptorError::InvalidDescriptorCharacter(*ch))? as u64;
+        c = poly_mod(c, pos & 31);
+        cls = cls * 3 + (pos >> 5);
+        clscount += 1;
+        if clscount == 3 {
+            c = poly_mod(c, cls);
+            cls = 0;
+            clscount = 0;
+        }
+    }
+    if clscount > 0 {
+        c = poly_mod(c, cls);
+    }
+    (0..8).for_each(|_| c = poly_mod(c, 0));
+    c ^= 1;
+
+    let mut checksum = [0_u8; 8];
+    for j in 0..8 {
+        checksum[j] = CHECKSUM_CHARSET[((c >> (5 * (7 - j))) & 31) as usize];
+    }
+
+    // if input data already had a checksum, check calculated checksum against original checksum
+    if let Some(original_checksum) = original_checksum {
+        if original_checksum.as_bytes() != checksum {
+            return Err(DescriptorError::InvalidDescriptorChecksum);
+        }
+    }
+
+    Ok(checksum)
+}
+
+/// Compute the checksum of a descriptor, excludes any existing checksum in the descriptor string from the calculation
+pub fn calc_checksum(desc: &str) -> Result<String, DescriptorError> {
+    // unsafe is okay here as the checksum only uses bytes in `CHECKSUM_CHARSET`
+    calc_checksum_bytes(desc).map(|b| unsafe { String::from_utf8_unchecked(b.to_vec()) })
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use crate::descriptor::calc_checksum;
+    use assert_matches::assert_matches;
+
+    // test calc_checksum() function; it should return the same value as Bitcoin Core
+    #[test]
+    fn test_calc_checksum() {
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)";
+        assert_eq!(calc_checksum(desc).unwrap(), "tqz0nc62");
+
+        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)";
+        assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs");
+    }
+
+    // test calc_checksum() function; it should return the same value as Bitcoin Core even if the
+    // descriptor string includes a checksum hash
+    #[test]
+    fn test_calc_checksum_with_checksum_hash() {
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc62";
+        assert_eq!(calc_checksum(desc).unwrap(), "tqz0nc62");
+
+        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)#lasegmfs";
+        assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs");
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc26";
+        assert_matches!(
+            calc_checksum(desc),
+            Err(DescriptorError::InvalidDescriptorChecksum)
+        );
+
+        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)#lasegmsf";
+        assert_matches!(
+            calc_checksum(desc),
+            Err(DescriptorError::InvalidDescriptorChecksum)
+        );
+    }
+
+    #[test]
+    fn test_calc_checksum_invalid_character() {
+        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!(
+            calc_checksum(&invalid_desc),
+            Err(DescriptorError::InvalidDescriptorCharacter(invalid_char)) if invalid_char == sparkle_heart.as_bytes()[0]
+        );
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/dsl.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/dsl.rs.html new file mode 100644 index 0000000000..81b6cf7d60 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/dsl.rs.html @@ -0,0 +1,2437 @@ +dsl.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
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+
// 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.
+
+//! Descriptors DSL
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_top_level_sh {
+    // disallow `sortedmulti` in `bare()`
+    ( Bare, new, new, Legacy, sortedmulti $( $inner:tt )* ) => {
+        compile_error!("`bare()` descriptors can't contain any `sortedmulti()` operands");
+    };
+    ( Bare, new, new, Legacy, sortedmulti_vec $( $inner:tt )* ) => {
+        compile_error!("`bare()` descriptors can't contain any `sortedmulti_vec()` operands");
+    };
+
+    ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, sortedmulti $( $inner:tt )* ) => {{
+        use core::marker::PhantomData;
+
+        use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
+        use $crate::miniscript::$ctx;
+
+        let build_desc = |k, pks| {
+            Ok((Descriptor::<DescriptorPublicKey>::$inner_struct($inner_struct::$sortedmulti_constructor(k, pks)?), PhantomData::<$ctx>))
+        };
+
+        $crate::impl_sortedmulti!(build_desc, sortedmulti $( $inner )*)
+    }};
+    ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, sortedmulti_vec $( $inner:tt )* ) => {{
+        use core::marker::PhantomData;
+
+        use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
+        use $crate::miniscript::$ctx;
+
+        let build_desc = |k, pks| {
+            Ok((Descriptor::<DescriptorPublicKey>::$inner_struct($inner_struct::$sortedmulti_constructor(k, pks)?), PhantomData::<$ctx>))
+        };
+
+        $crate::impl_sortedmulti!(build_desc, sortedmulti_vec $( $inner )*)
+    }};
+
+    ( $inner_struct:ident, $constructor:ident, $sortedmulti_constructor:ident, $ctx:ident, $( $minisc:tt )* ) => {{
+        use $crate::miniscript::descriptor::{$inner_struct, Descriptor, DescriptorPublicKey};
+
+        $crate::fragment!($( $minisc )*)
+            .and_then(|(minisc, keymap, networks)| Ok(($inner_struct::$constructor(minisc)?, keymap, networks)))
+            .and_then(|(inner, key_map, valid_networks)| Ok((Descriptor::<DescriptorPublicKey>::$inner_struct(inner), key_map, valid_networks)))
+    }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_top_level_pk {
+    ( $inner_type:ident, $ctx:ty, $key:expr ) => {{
+        use $crate::miniscript::descriptor::$inner_type;
+
+        #[allow(unused_imports)]
+        use $crate::keys::{DescriptorKey, IntoDescriptorKey};
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+
+        $key.into_descriptor_key()
+            .and_then(|key: DescriptorKey<$ctx>| key.extract(&secp))
+            .map_err($crate::descriptor::DescriptorError::Key)
+            .map(|(pk, key_map, valid_networks)| ($inner_type::new(pk), key_map, valid_networks))
+    }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_top_level_tr {
+    ( $internal_key:expr, $tap_tree:expr ) => {{
+        use $crate::miniscript::descriptor::{
+            Descriptor, DescriptorPublicKey, KeyMap, TapTree, Tr,
+        };
+        use $crate::miniscript::Tap;
+
+        #[allow(unused_imports)]
+        use $crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
+
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+
+        $internal_key
+            .into_descriptor_key()
+            .and_then(|key: DescriptorKey<Tap>| key.extract(&secp))
+            .map_err($crate::descriptor::DescriptorError::Key)
+            .and_then(|(pk, mut key_map, mut valid_networks)| {
+                let tap_tree = $tap_tree.map(
+                    |(tap_tree, tree_keymap, tree_networks): (
+                        TapTree<DescriptorPublicKey>,
+                        KeyMap,
+                        ValidNetworks,
+                    )| {
+                        key_map.extend(tree_keymap.into_iter());
+                        valid_networks =
+                            $crate::keys::merge_networks(&valid_networks, &tree_networks);
+
+                        tap_tree
+                    },
+                );
+
+                Ok((
+                    Descriptor::<DescriptorPublicKey>::Tr(Tr::new(pk, tap_tree)?),
+                    key_map,
+                    valid_networks,
+                ))
+            })
+    }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_leaf_opcode {
+    ( $terminal_variant:ident ) => {{
+        use $crate::descriptor::CheckMiniscript;
+
+        $crate::miniscript::Miniscript::from_ast(
+            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant,
+        )
+        .map_err($crate::descriptor::DescriptorError::Miniscript)
+        .and_then(|minisc| {
+            minisc.check_miniscript()?;
+            Ok(minisc)
+        })
+        .map(|minisc| {
+            (
+                minisc,
+                $crate::miniscript::descriptor::KeyMap::default(),
+                $crate::keys::any_network(),
+            )
+        })
+    }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_leaf_opcode_value {
+    ( $terminal_variant:ident, $value:expr ) => {{
+        use $crate::descriptor::CheckMiniscript;
+
+        $crate::miniscript::Miniscript::from_ast(
+            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($value),
+        )
+        .map_err($crate::descriptor::DescriptorError::Miniscript)
+        .and_then(|minisc| {
+            minisc.check_miniscript()?;
+            Ok(minisc)
+        })
+        .map(|minisc| {
+            (
+                minisc,
+                $crate::miniscript::descriptor::KeyMap::default(),
+                $crate::keys::any_network(),
+            )
+        })
+    }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_leaf_opcode_value_two {
+    ( $terminal_variant:ident, $one:expr, $two:expr ) => {{
+        use $crate::descriptor::CheckMiniscript;
+
+        $crate::miniscript::Miniscript::from_ast(
+            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($one, $two),
+        )
+        .map_err($crate::descriptor::DescriptorError::Miniscript)
+        .and_then(|minisc| {
+            minisc.check_miniscript()?;
+            Ok(minisc)
+        })
+        .map(|minisc| {
+            (
+                minisc,
+                $crate::miniscript::descriptor::KeyMap::default(),
+                $crate::keys::any_network(),
+            )
+        })
+    }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_node_opcode_two {
+    ( $terminal_variant:ident, $( $inner:tt )* ) => ({
+        use $crate::descriptor::CheckMiniscript;
+
+        let inner = $crate::fragment_internal!( @t $( $inner )* );
+        let (a, b) = $crate::descriptor::dsl::TupleTwo::from(inner).flattened();
+
+        a
+            .and_then(|a| Ok((a, b?)))
+            .and_then(|((a_minisc, mut a_keymap, a_networks), (b_minisc, b_keymap, b_networks))| {
+                // join key_maps
+                a_keymap.extend(b_keymap.into_iter());
+
+                let minisc = $crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
+                    $crate::alloc::sync::Arc::new(a_minisc),
+                    $crate::alloc::sync::Arc::new(b_minisc),
+                ))?;
+
+                minisc.check_miniscript()?;
+
+                Ok((minisc, a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
+            })
+    });
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_node_opcode_three {
+    ( $terminal_variant:ident, $( $inner:tt )* ) => ({
+        use $crate::descriptor::CheckMiniscript;
+
+        let inner = $crate::fragment_internal!( @t $( $inner )* );
+        let (a, b, c) = $crate::descriptor::dsl::TupleThree::from(inner).flattened();
+
+        a
+            .and_then(|a| Ok((a, b?, c?)))
+            .and_then(|((a_minisc, mut a_keymap, a_networks), (b_minisc, b_keymap, b_networks), (c_minisc, c_keymap, c_networks))| {
+                // join key_maps
+                a_keymap.extend(b_keymap.into_iter());
+                a_keymap.extend(c_keymap.into_iter());
+
+                let networks = $crate::keys::merge_networks(&a_networks, &b_networks);
+                let networks = $crate::keys::merge_networks(&networks, &c_networks);
+
+                let minisc = $crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
+                    $crate::alloc::sync::Arc::new(a_minisc),
+                    $crate::alloc::sync::Arc::new(b_minisc),
+                    $crate::alloc::sync::Arc::new(c_minisc),
+                ))?;
+
+                minisc.check_miniscript()?;
+
+                Ok((minisc, a_keymap, networks))
+            })
+    });
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_sortedmulti {
+    ( $build_desc:expr, sortedmulti_vec ( $thresh:expr, $keys:expr ) ) => ({
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+        $crate::keys::make_sortedmulti($thresh, $keys, $build_desc, &secp)
+    });
+    ( $build_desc:expr, sortedmulti ( $thresh:expr $(, $key:expr )+ ) ) => ({
+        use $crate::keys::IntoDescriptorKey;
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+
+        let keys = vec![
+            $(
+                $key.into_descriptor_key(),
+            )*
+        ];
+
+        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))
+    });
+
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! parse_tap_tree {
+    ( @merge $tree_a:expr, $tree_b:expr) => {{
+        use $crate::miniscript::descriptor::TapTree;
+
+        $tree_a
+            .and_then(|tree_a| Ok((tree_a, $tree_b?)))
+            .and_then(|((a_tree, mut a_keymap, a_networks), (b_tree, b_keymap, b_networks))| {
+                a_keymap.extend(b_keymap.into_iter());
+                Ok((TapTree::combine(a_tree, b_tree), a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
+            })
+
+    }};
+
+    // Two sub-trees
+    ( { { $( $tree_a:tt )* }, { $( $tree_b:tt )* } } ) => {{
+        let tree_a = $crate::parse_tap_tree!( { $( $tree_a )* } );
+        let tree_b = $crate::parse_tap_tree!( { $( $tree_b )* } );
+
+        $crate::parse_tap_tree!(@merge tree_a, tree_b)
+    }};
+
+    // One leaf and a sub-tree
+    ( { $op_a:ident ( $( $minisc_a:tt )* ), { $( $tree_b:tt )* } } ) => {{
+        let tree_a = $crate::parse_tap_tree!( $op_a ( $( $minisc_a )* ) );
+        let tree_b = $crate::parse_tap_tree!( { $( $tree_b )* } );
+
+        $crate::parse_tap_tree!(@merge tree_a, tree_b)
+    }};
+    ( { { $( $tree_a:tt )* }, $op_b:ident ( $( $minisc_b:tt )* ) } ) => {{
+        let tree_a = $crate::parse_tap_tree!( { $( $tree_a )* } );
+        let tree_b = $crate::parse_tap_tree!( $op_b ( $( $minisc_b )* ) );
+
+        $crate::parse_tap_tree!(@merge tree_a, tree_b)
+    }};
+
+    // Two leaves
+    ( { $op_a:ident ( $( $minisc_a:tt )* ), $op_b:ident ( $( $minisc_b:tt )* ) } ) => {{
+        let tree_a = $crate::parse_tap_tree!( $op_a ( $( $minisc_a )* ) );
+        let tree_b = $crate::parse_tap_tree!( $op_b ( $( $minisc_b )* ) );
+
+        $crate::parse_tap_tree!(@merge tree_a, tree_b)
+    }};
+
+    // Single leaf
+    ( $op:ident ( $( $minisc:tt )* ) ) => {{
+        use $crate::alloc::sync::Arc;
+        use $crate::miniscript::descriptor::TapTree;
+
+        $crate::fragment!( $op ( $( $minisc )* ) )
+            .map(|(a_minisc, a_keymap, a_networks)| (TapTree::Leaf(Arc::new(a_minisc)), a_keymap, a_networks))
+    }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! apply_modifier {
+    ( $terminal_variant:ident, $inner:expr ) => {{
+        use $crate::descriptor::CheckMiniscript;
+
+        $inner
+            .map_err(|e| -> $crate::descriptor::DescriptorError { e.into() })
+            .and_then(|(minisc, keymap, networks)| {
+                let minisc = $crate::miniscript::Miniscript::from_ast(
+                    $crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
+                        $crate::alloc::sync::Arc::new(minisc),
+                    ),
+                )?;
+
+                minisc.check_miniscript()?;
+
+                Ok((minisc, keymap, networks))
+            })
+    }};
+
+    ( a: $inner:expr ) => {{
+        $crate::apply_modifier!(Alt, $inner)
+    }};
+    ( s: $inner:expr ) => {{
+        $crate::apply_modifier!(Swap, $inner)
+    }};
+    ( c: $inner:expr ) => {{
+        $crate::apply_modifier!(Check, $inner)
+    }};
+    ( d: $inner:expr ) => {{
+        $crate::apply_modifier!(DupIf, $inner)
+    }};
+    ( v: $inner:expr ) => {{
+        $crate::apply_modifier!(Verify, $inner)
+    }};
+    ( j: $inner:expr ) => {{
+        $crate::apply_modifier!(NonZero, $inner)
+    }};
+    ( n: $inner:expr ) => {{
+        $crate::apply_modifier!(ZeroNotEqual, $inner)
+    }};
+
+    // Modifiers expanded to other operators
+    ( t: $inner:expr ) => {{
+        $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
+            $crate::impl_leaf_opcode_value_two!(
+                AndV,
+                $crate::alloc::sync::Arc::new(a_minisc),
+                $crate::alloc::sync::Arc::new($crate::fragment!(true).unwrap().0)
+            )
+            .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
+        })
+    }};
+    ( l: $inner:expr ) => {{
+        $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
+            $crate::impl_leaf_opcode_value_two!(
+                OrI,
+                $crate::alloc::sync::Arc::new($crate::fragment!(false).unwrap().0),
+                $crate::alloc::sync::Arc::new(a_minisc)
+            )
+            .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
+        })
+    }};
+    ( u: $inner:expr ) => {{
+        $inner.and_then(|(a_minisc, a_keymap, a_networks)| {
+            $crate::impl_leaf_opcode_value_two!(
+                OrI,
+                $crate::alloc::sync::Arc::new(a_minisc),
+                $crate::alloc::sync::Arc::new($crate::fragment!(false).unwrap().0)
+            )
+            .map(|(minisc, _, _)| (minisc, a_keymap, a_networks))
+        })
+    }};
+}
+
+/// Macro to write full descriptors with code
+///
+/// This macro expands to a `Result` of
+/// [`DescriptorTemplateOut`](super::template::DescriptorTemplateOut) and [`DescriptorError`](crate::descriptor::DescriptorError)
+///
+/// The syntax is very similar to the normal descriptor syntax, with the exception that modifiers
+/// cannot be grouped together. For instance, a descriptor fragment like `sdv:older(144)` has to be
+/// broken up to `s:d:v:older(144)`.
+///
+/// The `pk()`, `pk_k()` and `pk_h()` operands can take as argument any type that implements
+/// [`IntoDescriptorKey`]. This means that keys can also be written inline as strings, but in that
+/// case they must be wrapped in quotes, which is another difference compared to the standard
+/// descriptor syntax.
+///
+/// [`IntoDescriptorKey`]: crate::keys::IntoDescriptorKey
+///
+/// ## Example
+///
+/// Signature plus timelock descriptor:
+///
+/// ```
+/// # use std::str::FromStr;
+/// let (my_descriptor, my_keys_map, networks) = bdk_wallet::descriptor!(sh(wsh(and_v(v:pk("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"),older(50)))))?;
+/// # Ok::<(), Box<dyn std::error::Error>>(())
+/// ```
+///
+/// -------
+///
+/// 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.
+///
+/// They both produce the descriptor: `wsh(thresh(2,pk(...),s:pk(...),sndv:older(...)))`
+///
+/// ```
+/// # use std::str::FromStr;
+/// let my_key_1 = bitcoin::PublicKey::from_str(
+///     "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
+/// )?;
+/// let my_key_2 =
+///     bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
+/// let my_timelock = 50;
+///
+/// let (descriptor_a, key_map_a, networks) = bdk_wallet::descriptor! {
+///     wsh (
+///         thresh(2, pk(my_key_1), s:pk(my_key_2), s:n:d:v:older(my_timelock))
+///     )
+/// }?;
+///
+/// #[rustfmt::skip]
+/// let b_items = vec![
+///     bdk_wallet::fragment!(pk(my_key_1))?,
+///     bdk_wallet::fragment!(s:pk(my_key_2))?,
+///     bdk_wallet::fragment!(s:n:d:v:older(my_timelock))?,
+/// ];
+/// let (descriptor_b, mut key_map_b, networks) =
+///     bdk_wallet::descriptor!(wsh(thresh_vec(2, b_items)))?;
+///
+/// assert_eq!(descriptor_a, descriptor_b);
+/// assert_eq!(key_map_a.len(), key_map_b.len());
+/// # Ok::<(), Box<dyn std::error::Error>>(())
+/// ```
+///
+/// ------
+///
+/// Simple 2-of-2 multi-signature, equivalent to: `wsh(multi(2, ...))`
+///
+/// ```
+/// # use std::str::FromStr;
+/// let my_key_1 = bitcoin::PublicKey::from_str(
+///     "02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c",
+/// )?;
+/// let my_key_2 =
+///     bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
+///
+/// let (descriptor, key_map, networks) = bdk_wallet::descriptor! {
+///     wsh (
+///         multi(2, my_key_1, my_key_2)
+///     )
+/// }?;
+/// # Ok::<(), Box<dyn std::error::Error>>(())
+/// ```
+///
+/// ------
+///
+/// Native-Segwit single-sig, equivalent to: `wpkh(...)`
+///
+/// ```
+/// let my_key =
+///     bitcoin::PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy")?;
+///
+/// let (descriptor, key_map, networks) = bdk_wallet::descriptor!(wpkh(my_key))?;
+/// # Ok::<(), Box<dyn std::error::Error>>(())
+/// ```
+///
+/// [`Vec`]: alloc::vec::Vec
+#[macro_export]
+macro_rules! descriptor {
+    ( bare ( $( $minisc:tt )* ) ) => ({
+        $crate::impl_top_level_sh!(Bare, new, new, Legacy, $( $minisc )*)
+    });
+    ( sh ( wsh ( $( $minisc:tt )* ) ) ) => ({
+        $crate::descriptor!(shwsh ($( $minisc )*))
+    });
+    ( shwsh ( $( $minisc:tt )* ) ) => ({
+        $crate::impl_top_level_sh!(Sh, new_wsh, new_wsh_sortedmulti, Segwitv0, $( $minisc )*)
+    });
+    ( pk ( $key:expr ) ) => ({
+        // `pk()` is actually implemented as `bare(pk())`
+        $crate::descriptor!( bare ( pk ( $key ) ) )
+    });
+    ( pkh ( $key:expr ) ) => ({
+        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
+
+        $crate::impl_top_level_pk!(Pkh, $crate::miniscript::Legacy, $key)
+            .and_then(|(a, b, c)| Ok((a.map_err(|e| miniscript::Error::from(e))?, b, c)))
+            .map(|(a, b, c)| (Descriptor::<DescriptorPublicKey>::Pkh(a), b, c))
+    });
+    ( wpkh ( $key:expr ) ) => ({
+        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey};
+
+        $crate::impl_top_level_pk!(Wpkh, $crate::miniscript::Segwitv0, $key)
+            .and_then(|(a, b, c)| Ok((a.map_err(|e| miniscript::Error::from(e))?, b, c)))
+            .map(|(a, b, c)| (Descriptor::<DescriptorPublicKey>::Wpkh(a), b, c))
+    });
+    ( sh ( wpkh ( $key:expr ) ) ) => ({
+        $crate::descriptor!(shwpkh ( $key ))
+    });
+    ( shwpkh ( $key:expr ) ) => ({
+        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey, Sh};
+
+        $crate::impl_top_level_pk!(Wpkh, $crate::miniscript::Segwitv0, $key)
+            .and_then(|(a, b, c)| Ok((a.map_err(|e| miniscript::Error::from(e))?, b, c)))
+            .and_then(|(a, b, c)| Ok((Descriptor::<DescriptorPublicKey>::Sh(Sh::new_wpkh(a.into_inner())?), b, c)))
+    });
+    ( sh ( $( $minisc:tt )* ) ) => ({
+        $crate::impl_top_level_sh!(Sh, new, new_sortedmulti, Legacy, $( $minisc )*)
+    });
+    ( wsh ( $( $minisc:tt )* ) ) => ({
+        $crate::impl_top_level_sh!(Wsh, new, new_sortedmulti, Segwitv0, $( $minisc )*)
+    });
+
+    ( tr ( $internal_key:expr ) ) => ({
+        $crate::impl_top_level_tr!($internal_key, None)
+    });
+    ( tr ( $internal_key:expr, $( $taptree:tt )* ) ) => ({
+        let tap_tree = $crate::parse_tap_tree!( $( $taptree )* );
+        tap_tree
+            .and_then(|tap_tree| $crate::impl_top_level_tr!($internal_key, Some(tap_tree)))
+    });
+}
+
+#[doc(hidden)]
+pub struct TupleTwo<A, B> {
+    pub a: A,
+    pub b: B,
+}
+
+impl<A, B> TupleTwo<A, B> {
+    pub fn flattened(self) -> (A, B) {
+        (self.a, self.b)
+    }
+}
+
+impl<A, B> From<(A, (B, ()))> for TupleTwo<A, B> {
+    fn from((a, (b, _)): (A, (B, ()))) -> Self {
+        TupleTwo { a, b }
+    }
+}
+
+#[doc(hidden)]
+pub struct TupleThree<A, B, C> {
+    pub a: A,
+    pub b: B,
+    pub c: C,
+}
+
+impl<A, B, C> TupleThree<A, B, C> {
+    pub fn flattened(self) -> (A, B, C) {
+        (self.a, self.b, self.c)
+    }
+}
+
+impl<A, B, C> From<(A, (B, (C, ())))> for TupleThree<A, B, C> {
+    fn from((a, (b, (c, _))): (A, (B, (C, ())))) -> Self {
+        TupleThree { a, b, c }
+    }
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! group_multi_keys {
+    ( $( $key:expr ),+ ) => {{
+        use $crate::keys::IntoDescriptorKey;
+
+        let keys = vec![
+            $(
+                $key.into_descriptor_key(),
+            )*
+        ];
+
+        keys.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
+            .map_err($crate::descriptor::DescriptorError::Key)
+    }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! fragment_internal {
+    // The @v prefix is used to parse a sequence of operands and return them in a vector. This is
+    // used by operands that take a variable number of arguments, like `thresh()` and `multi()`.
+    ( @v $op:ident ( $( $args:tt )* ) $( $tail:tt )* ) => ({
+        let mut v = vec![$crate::fragment!( $op ( $( $args )* ) )];
+        v.append(&mut $crate::fragment_internal!( @v $( $tail )* ));
+
+        v
+    });
+    // Match modifiers
+    ( @v $modif:tt : $( $tail:tt )* ) => ({
+        let mut v = $crate::fragment_internal!( @v $( $tail )* );
+        let first = v.drain(..1).next().unwrap();
+
+        let first = $crate::apply_modifier!($modif:first);
+
+        let mut v_final = vec![first];
+        v_final.append(&mut v);
+
+        v_final
+    });
+    // Remove commas between operands
+    ( @v , $( $tail:tt )* ) => ({
+        $crate::fragment_internal!( @v $( $tail )* )
+    });
+    ( @v ) => ({
+        vec![]
+    });
+
+    // The @t prefix is used to parse a sequence of operands and return them in a tuple. This
+    // allows checking at compile-time the number of arguments passed to an operand. For this
+    // reason it's used by `and_*()`, `or_*()`, etc.
+    //
+    // Unfortunately, due to the fact that concatenating tuples is pretty hard, the final result
+    // adds in the first spot the parsed operand and in the second spot the result of parsing
+    // all the following ones. For two operands the type then corresponds to: (X, (X, ())). For
+    // three operands it's (X, (X, (X, ()))), etc.
+    //
+    // To check that the right number of arguments has been passed we can "cast" those tuples to
+    // more convenient structures like `TupleTwo`. If the conversion succeeds, the right number of
+    // args was passed. Otherwise the compilation fails entirely.
+    ( @t $op:ident ( $( $args:tt )* ) $( $tail:tt )* ) => ({
+        ($crate::fragment!( $op ( $( $args )* ) ), $crate::fragment_internal!( @t $( $tail )* ))
+    });
+    // Match modifiers
+    ( @t $modif:tt : $( $tail:tt )* ) => ({
+        let (first, tail) = $crate::fragment_internal!( @t $( $tail )* );
+        ($crate::apply_modifier!($modif:first), tail)
+    });
+    // Remove commas between operands
+    ( @t , $( $tail:tt )* ) => ({
+        $crate::fragment_internal!( @t $( $tail )* )
+    });
+    ( @t ) => ({});
+
+    // Fallback to calling `fragment!()`
+    ( $( $tokens:tt )* ) => ({
+        $crate::fragment!($( $tokens )*)
+    });
+}
+
+/// Macro to write descriptor fragments with code
+///
+/// This macro will be expanded to an object of type `Result<(Miniscript<DescriptorPublicKey, _>, KeyMap, ValidNetworks), DescriptorError>`. It allows writing
+/// fragments of larger descriptors that can be pieced together using `fragment!(thresh_vec(m, ...))`.
+///
+/// The syntax to write macro fragment is the same as documented for the [`descriptor`] macro.
+#[macro_export]
+macro_rules! fragment {
+    // Modifiers
+    ( $modif:tt : $( $tail:tt )* ) => ({
+        let op = $crate::fragment!( $( $tail )* );
+        $crate::apply_modifier!($modif:op)
+    });
+
+    // Miniscript
+    ( true ) => ({
+        $crate::impl_leaf_opcode!(True)
+    });
+    ( false ) => ({
+        $crate::impl_leaf_opcode!(False)
+    });
+    ( pk_k ( $key:expr ) ) => ({
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+        $crate::keys::make_pk($key, &secp)
+    });
+    ( pk ( $key:expr ) ) => ({
+        $crate::fragment!(c:pk_k ( $key ))
+    });
+    ( pk_h ( $key:expr ) ) => ({
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+        $crate::keys::make_pkh($key, &secp)
+    });
+    ( after ( $value:expr ) ) => ({
+        $crate::impl_leaf_opcode_value!(After, $crate::miniscript::AbsLockTime::from_consensus($value))
+    });
+    ( older ( $value:expr ) ) => ({
+        $crate::impl_leaf_opcode_value!(Older, $crate::bitcoin::Sequence($value)) // TODO!!
+    });
+    ( sha256 ( $hash:expr ) ) => ({
+        $crate::impl_leaf_opcode_value!(Sha256, $hash)
+    });
+    ( hash256 ( $hash:expr ) ) => ({
+        $crate::impl_leaf_opcode_value!(Hash256, $hash)
+    });
+    ( ripemd160 ( $hash:expr ) ) => ({
+        $crate::impl_leaf_opcode_value!(Ripemd160, $hash)
+    });
+    ( hash160 ( $hash:expr ) ) => ({
+        $crate::impl_leaf_opcode_value!(Hash160, $hash)
+    });
+    ( and_v ( $( $inner:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(AndV, $( $inner )*)
+    });
+    ( and_b ( $( $inner:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(AndB, $( $inner )*)
+    });
+    ( and_or ( $( $inner:tt )* ) ) => ({
+        $crate::impl_node_opcode_three!(AndOr, $( $inner )*)
+    });
+    ( andor ( $( $inner:tt )* ) ) => ({
+        $crate::impl_node_opcode_three!(AndOr, $( $inner )*)
+    });
+    ( or_b ( $( $inner:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(OrB, $( $inner )*)
+    });
+    ( or_d ( $( $inner:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(OrD, $( $inner )*)
+    });
+    ( or_c ( $( $inner:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(OrC, $( $inner )*)
+    });
+    ( or_i ( $( $inner:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(OrI, $( $inner )*)
+    });
+    ( thresh_vec ( $thresh:expr, $items:expr ) ) => ({
+        use $crate::miniscript::descriptor::KeyMap;
+
+        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());
+            let net_acc = $crate::keys::merge_networks(&net_acc, &net);
+
+            (keys_acc, net_acc)
+        });
+
+        $crate::impl_leaf_opcode_value_two!(Thresh, $thresh, items)
+            .map(|(minisc, _, _)| (minisc, key_maps, valid_networks))
+    });
+    ( thresh ( $thresh:expr, $( $inner:tt )* ) ) => ({
+        let items = $crate::fragment_internal!( @v $( $inner )* );
+
+        items.into_iter().collect::<Result<$crate::alloc::vec::Vec<_>, _>>()
+            .and_then(|items| $crate::fragment!(thresh_vec($thresh, items)))
+    });
+    ( multi_vec ( $thresh:expr, $keys:expr ) ) => ({
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+
+        $crate::keys::make_multi($thresh, $crate::miniscript::Terminal::Multi, $keys, &secp)
+    });
+    ( multi ( $thresh:expr $(, $key:expr )+ ) ) => ({
+        $crate::group_multi_keys!( $( $key ),* )
+            .and_then(|keys| $crate::fragment!( multi_vec ( $thresh, keys ) ))
+    });
+    ( multi_a_vec ( $thresh:expr, $keys:expr ) ) => ({
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+
+        $crate::keys::make_multi($thresh, $crate::miniscript::Terminal::MultiA, $keys, &secp)
+    });
+    ( multi_a ( $thresh:expr $(, $key:expr )+ ) ) => ({
+        $crate::group_multi_keys!( $( $key ),* )
+            .and_then(|keys| $crate::fragment!( multi_a_vec ( $thresh, keys ) ))
+    });
+
+    // `sortedmulti()` is handled separately
+    ( sortedmulti ( $( $inner:tt )* ) ) => ({
+        compile_error!("`sortedmulti` can only be used as the root operand of a descriptor");
+    });
+    ( sortedmulti_vec ( $( $inner:tt )* ) ) => ({
+        compile_error!("`sortedmulti_vec` can only be used as the root operand of a descriptor");
+    });
+}
+
+#[cfg(test)]
+mod test {
+    use alloc::string::ToString;
+    use bitcoin::secp256k1::Secp256k1;
+    use miniscript::descriptor::{DescriptorPublicKey, KeyMap};
+    use miniscript::{Descriptor, Legacy, Segwitv0};
+
+    use core::str::FromStr;
+
+    use crate::descriptor::{DescriptorError, DescriptorMeta};
+    use crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
+    use bitcoin::bip32;
+    use bitcoin::Network::{Bitcoin, Regtest, Signet, Testnet};
+    use bitcoin::PrivateKey;
+
+    // test the descriptor!() macro
+
+    // verify descriptor generates expected script(s) (if bare or pk) or address(es)
+    fn check(
+        desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>,
+        is_witness: bool,
+        is_fixed: bool,
+        expected: &[&str],
+    ) {
+        let (desc, _key_map, _networks) = desc.unwrap();
+        assert_eq!(desc.is_witness(), is_witness);
+        assert_eq!(!desc.has_wildcard(), is_fixed);
+        for i in 0..expected.len() {
+            let child_desc = desc
+                .at_derivation_index(i as u32)
+                .expect("i is not hardened");
+            let address = child_desc.address(Regtest);
+            if let Ok(address) = address {
+                assert_eq!(address.to_string(), *expected.get(i).unwrap());
+            } else {
+                let script = child_desc.script_pubkey();
+                assert_eq!(script.to_hex_string(), *expected.get(i).unwrap());
+            }
+        }
+    }
+
+    // - at least one of each "type" of operator; i.e. one modifier, one leaf_opcode, one leaf_opcode_value, etc.
+    // - mixing up key types that implement IntoDescriptorKey in multi() or thresh()
+
+    // expected script for pk and bare manually created
+    // expected addresses created with `bitcoin-cli getdescriptorinfo` (for hash) and `bitcoin-cli deriveaddresses`
+
+    #[test]
+    fn test_fixed_legacy_descriptors() {
+        let pubkey1 = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        let pubkey2 = bitcoin::PublicKey::from_str(
+            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
+        )
+        .unwrap();
+
+        check(
+            descriptor!(bare(multi(1,pubkey1,pubkey2))),
+            false,
+            true,
+            &["512103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af52ae"],
+        );
+        check(
+            descriptor!(pk(pubkey1)),
+            false,
+            true,
+            &["2103a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bdac"],
+        );
+        check(
+            descriptor!(pkh(pubkey1)),
+            false,
+            true,
+            &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
+        );
+        check(
+            descriptor!(sh(multi(1, pubkey1, pubkey2))),
+            false,
+            true,
+            &["2MymURoV1bzuMnWMGiXzyomDkeuxXY7Suey"],
+        );
+    }
+
+    #[test]
+    fn test_fixed_segwitv0_descriptors() {
+        let pubkey1 = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        let pubkey2 = bitcoin::PublicKey::from_str(
+            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
+        )
+        .unwrap();
+
+        check(
+            descriptor!(wpkh(pubkey1)),
+            true,
+            true,
+            &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
+        );
+        check(
+            descriptor!(sh(wpkh(pubkey1))),
+            true,
+            true,
+            &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
+        );
+        check(
+            descriptor!(wsh(multi(1, pubkey1, pubkey2))),
+            true,
+            true,
+            &["bcrt1qgw8jvv2hsrvjfa6q66rk6har7d32lrqm5unnf5cl63q9phxfvgps5fyfqe"],
+        );
+        check(
+            descriptor!(sh(wsh(multi(1, pubkey1, pubkey2)))),
+            true,
+            true,
+            &["2NCidRJysy7apkmE6JF5mLLaJFkrN3Ub9iy"],
+        );
+    }
+
+    #[test]
+    fn test_fixed_threeop_descriptors() {
+        let redeem_key = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        let move_key = bitcoin::PublicKey::from_str(
+            "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
+        )
+        .unwrap();
+
+        check(
+            descriptor!(sh(wsh(and_or(pk(redeem_key), older(1000), pk(move_key))))),
+            true,
+            true,
+            &["2MypGwr5eQWAWWJtiJgUEToVxc4zuokjQRe"],
+        );
+    }
+
+    #[test]
+    fn test_bip32_legacy_descriptors() {
+        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+
+        let path = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
+        check(
+            descriptor!(pk(desc_key)),
+            false,
+            false,
+            &[
+                "2102363ad03c10024e1b597a5b01b9982807fb638e00b06f3b2d4a89707de3b93c37ac",
+                "2102063a21fd780df370ed2fc8c4b86aa5ea642630609c203009df631feb7b480dd2ac",
+                "2102ba2685ad1fa5891cb100f1656b2ce3801822ccb9bac0336734a6f8c1b93ebbc0ac",
+            ],
+        );
+
+        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
+        check(
+            descriptor!(pkh(desc_key)),
+            false,
+            false,
+            &[
+                "muvBdsVpJxpFuTHMKA47htJPdCvdt4F9DP",
+                "mxQSHK7DL2t1DN3xFxov1janCoXSSkrSPj",
+                "mfz43r15GiWo4nizmyzMNubsnkDpByFFAn",
+            ],
+        );
+
+        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
+        let desc_key1 = (xprv, path).into_descriptor_key().unwrap();
+        let desc_key2 = (xprv, path2).into_descriptor_key().unwrap();
+
+        check(
+            descriptor!(sh(multi(1, desc_key1, desc_key2))),
+            false,
+            false,
+            &[
+                "2MtMDXsfwefZkEEhVViEPidvcKRUtJamJJ8",
+                "2MwAUZ1NYyWjhVvGTethFL6n7nZhS8WE6At",
+                "2MuT6Bj66HLwZd7s4SoD8XbK4GwriKEA6Gr",
+            ],
+        );
+    }
+
+    #[test]
+    fn test_bip32_segwitv0_descriptors() {
+        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+
+        let path = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
+        check(
+            descriptor!(wpkh(desc_key)),
+            true,
+            false,
+            &[
+                "bcrt1qnhm8w9fhc8cxzgqsmqdf9fyjccyvc0gltnymu0",
+                "bcrt1qhylfd55rn75w9fj06zspctad5w4hz33rf0ttad",
+                "bcrt1qq5sq3a6k9av9d8cne0k9wcldy4nqey5yt6889r",
+            ],
+        );
+
+        let desc_key = (xprv, path.clone()).into_descriptor_key().unwrap();
+        check(
+            descriptor!(sh(wpkh(desc_key))),
+            true,
+            false,
+            &[
+                "2MxvjQCaLqZ5QxZ7XotZDQ63hZw3NPss763",
+                "2NDUoevN4QMzhvHDMGhKuiT2fN9HXbFRMwn",
+                "2NF4BEAY2jF1Fu8vqfN3NVKoFtom77pUxrx",
+            ],
+        );
+
+        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
+        let desc_key1 = (xprv, path.clone()).into_descriptor_key().unwrap();
+        let desc_key2 = (xprv, path2.clone()).into_descriptor_key().unwrap();
+        check(
+            descriptor!(wsh(multi(1, desc_key1, desc_key2))),
+            true,
+            false,
+            &[
+                "bcrt1qfxv8mxmlv5sz8q2mnuyaqdfe9jr4vvmx0csjhn092p6f4qfygfkq2hng49",
+                "bcrt1qerj85g243e6jlcdxpmn9spk0gefcwvu7nw7ee059d5ydzpdhkm2qwfkf5k",
+                "bcrt1qxkl2qss3k58q9ktc8e89pwr4gnptfpw4hju4xstxcjc0hkcae3jstluty7",
+            ],
+        );
+
+        let desc_key1 = (xprv, path).into_descriptor_key().unwrap();
+        let desc_key2 = (xprv, path2).into_descriptor_key().unwrap();
+        check(
+            descriptor!(sh(wsh(multi(1, desc_key1, desc_key2)))),
+            true,
+            false,
+            &[
+                "2NFCtXvx9q4ci2kvKub17iSTgvRXGctCGhz",
+                "2NB2PrFPv5NxWCpygas8tPrGJG2ZFgeuwJw",
+                "2N79ZAGo5cMi5Jt7Wo9L5YmF5GkEw7sjWdC",
+            ],
+        );
+    }
+
+    #[test]
+    fn test_dsl_sortedmulti() {
+        let key_1 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        let path_1 = bip32::DerivationPath::from_str("m/0").unwrap();
+
+        let key_2 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
+        let path_2 = bip32::DerivationPath::from_str("m/1").unwrap();
+
+        let desc_key1 = (key_1, path_1);
+        let desc_key2 = (key_2, path_2);
+
+        check(
+            descriptor!(sh(sortedmulti(1, desc_key1.clone(), desc_key2.clone()))),
+            false,
+            false,
+            &[
+                "2MsxzPEJDBzpGffJXPaDpfXZAUNnZhaMh2N",
+                "2My3x3DLPK3UbGWGpxrXr1RnbD8MNC4FpgS",
+                "2NByEuiQT7YLqHCTNxL5KwYjvtuCYcXNBSC",
+                "2N1TGbP81kj2VUKTSWgrwxoMfuWjvfUdyu7",
+                "2N3Bomq2fpAcLRNfZnD3bCWK9quan28CxCR",
+                "2N9nrZaEzEFDqEAU9RPvDnXGT6AVwBDKAQb",
+            ],
+        );
+
+        check(
+            descriptor!(sh(wsh(sortedmulti(
+                1,
+                desc_key1.clone(),
+                desc_key2.clone()
+            )))),
+            true,
+            false,
+            &[
+                "2NCogc5YyM4N6ruv1hUa7WLMW1BPeCK7N9B",
+                "2N6mkSAKi1V2oaBXby7XHdvBMKEDRQcFpNe",
+                "2NFmTSttm9v6bXeoWaBvpMcgfPQcZhNn3Eh",
+                "2Mvib87RBPUHXNEpX5S5Kv1qqrhBfgBGsJM",
+                "2MtMv5mcK2EjcLsH8Txpx2JxLLzHr4ttczL",
+                "2MsWCB56rb4T6yPv8QudZGHERTwNgesE4f6",
+            ],
+        );
+
+        check(
+            descriptor!(wsh(sortedmulti_vec(1, vec![desc_key1, desc_key2]))),
+            true,
+            false,
+            &[
+                "bcrt1qcvq0lg8q7a47ytrd7zk5y7uls7mulrenjgvflwylpppgwf8029es4vhpnj",
+                "bcrt1q80yn8sdt6l7pjvkz25lglyaqctlmsq9ugk80rmxt8yu0npdsj97sc7l4de",
+                "bcrt1qrvf6024v9s50qhffe3t2fr2q9ckdhx2g6jz32chm2pp24ymgtr5qfrdmct",
+                "bcrt1q6srfmra0ynypym35c7jvsxt2u4yrugeajq95kg2ps7lk6h2gaunsq9lzxn",
+                "bcrt1qhl8rrzzcdpu7tcup3lcg7tge52sqvwy5fcv4k78v6kxtwmqf3v6qpvyjza",
+                "bcrt1ql2elz9mhm9ll27ddpewhxs732xyl2fk2kpkqz9gdyh33wgcun4vstrd49k",
+            ],
+        );
+    }
+
+    // - verify the valid_networks returned is correctly computed based on the keys present in the descriptor
+    #[test]
+    fn test_valid_networks() {
+        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        let path = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key = (xprv, path).into_descriptor_key().unwrap();
+
+        let (_desc, _key_map, valid_networks) = descriptor!(pkh(desc_key)).unwrap();
+        assert_eq!(
+            valid_networks,
+            [Testnet, Regtest, Signet].iter().cloned().collect()
+        );
+
+        let xprv = bip32::Xpriv::from_str("xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").unwrap();
+        let path = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
+        let desc_key = (xprv, path).into_descriptor_key().unwrap();
+
+        let (_desc, _key_map, valid_networks) = descriptor!(wpkh(desc_key)).unwrap();
+        assert_eq!(valid_networks, [Bitcoin].iter().cloned().collect());
+    }
+
+    // - verify the key_maps are correctly merged together
+    #[test]
+    fn test_key_maps_merged() {
+        let secp = Secp256k1::new();
+
+        let xprv1 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        let path1 = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key1 = (xprv1, path1.clone()).into_descriptor_key().unwrap();
+
+        let xprv2 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
+        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
+        let desc_key2 = (xprv2, path2.clone()).into_descriptor_key().unwrap();
+
+        let xprv3 = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf").unwrap();
+        let path3 = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
+        let desc_key3 = (xprv3, path3.clone()).into_descriptor_key().unwrap();
+
+        let (_desc, key_map, _valid_networks) =
+            descriptor!(sh(wsh(multi(2, desc_key1, desc_key2, desc_key3)))).unwrap();
+        assert_eq!(key_map.len(), 3);
+
+        let desc_key1: DescriptorKey<Segwitv0> = (xprv1, path1).into_descriptor_key().unwrap();
+        let desc_key2: DescriptorKey<Segwitv0> = (xprv2, path2).into_descriptor_key().unwrap();
+        let desc_key3: DescriptorKey<Segwitv0> = (xprv3, path3).into_descriptor_key().unwrap();
+
+        let (key1, _key_map, _valid_networks) = desc_key1.extract(&secp).unwrap();
+        let (key2, _key_map, _valid_networks) = desc_key2.extract(&secp).unwrap();
+        let (key3, _key_map, _valid_networks) = desc_key3.extract(&secp).unwrap();
+        assert_eq!(key_map.get(&key1).unwrap().to_string(), "tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy/0/*");
+        assert_eq!(key_map.get(&key2).unwrap().to_string(), "tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF/2147483647'/0/*");
+        assert_eq!(key_map.get(&key3).unwrap().to_string(), "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf/10/20/30/40/*");
+    }
+
+    // - verify the ScriptContext is correctly validated (i.e. passing a type that only impl IntoDescriptorKey<Segwitv0> to a pkh() descriptor should throw a compilation error
+    #[test]
+    fn test_script_context_validation() {
+        // this compiles
+        let xprv = bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        let path = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key: DescriptorKey<Legacy> = (xprv, path).into_descriptor_key().unwrap();
+
+        let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
+        assert_eq!(desc.to_string(), "pkh(tpubD6NzVbkrYhZ4WR7a4vY1VT3khMJMeAxVsfq9TBJyJWrNk247zCJtV7AWf6UJP7rAVsn8NNKdJi3gFyKPTmWZS9iukb91xbn2HbFSMQm2igY/0/*)#yrnz9pp2");
+
+        // as expected this does not compile due to invalid context
+        //let desc_key:DescriptorKey<Segwitv0> = (xprv, path.clone()).into_descriptor_key().unwrap();
+        //let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
+    }
+
+    #[test]
+    fn test_dsl_modifiers() {
+        let private_key =
+            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
+        let (descriptor, _, _) =
+            descriptor!(wsh(thresh(2,n:d:v:older(1),s:pk(private_key),s:pk(private_key)))).unwrap();
+
+        assert_eq!(descriptor.to_string(), "wsh(thresh(2,ndv:older(1),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)))#zzk3ux8g")
+    }
+
+    #[test]
+    #[should_panic(expected = "Miniscript(ContextError(UncompressedKeysNotAllowed))")]
+    fn test_dsl_miniscript_checks() {
+        let mut uncompressed_pk =
+            PrivateKey::from_wif("L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6").unwrap();
+        uncompressed_pk.compressed = false;
+
+        descriptor!(wsh(v: pk(uncompressed_pk))).unwrap();
+    }
+
+    #[test]
+    fn test_dsl_tr_only_key() {
+        let private_key =
+            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
+        let (descriptor, _, _) = descriptor!(tr(private_key)).unwrap();
+
+        assert_eq!(
+            descriptor.to_string(),
+            "tr(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)#heq9m95v"
+        )
+    }
+
+    #[test]
+    fn test_dsl_tr_simple_tree() {
+        let private_key =
+            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
+        let (descriptor, _, _) =
+            descriptor!(tr(private_key, { pk(private_key), pk(private_key) })).unwrap();
+
+        assert_eq!(descriptor.to_string(), "tr(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c,{pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)})#xy5fjw6d")
+    }
+
+    #[test]
+    fn test_dsl_tr_single_leaf() {
+        let private_key =
+            PrivateKey::from_wif("cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR").unwrap();
+        let (descriptor, _, _) = descriptor!(tr(private_key, pk(private_key))).unwrap();
+
+        assert_eq!(descriptor.to_string(), "tr(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c,pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c))#lzl2vmc7")
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/error.rs.html new file mode 100644 index 0000000000..ce7b6edaf5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/error.rs.html @@ -0,0 +1,249 @@ +error.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
+
// 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.
+
+//! Descriptor errors
+use core::fmt;
+
+/// Errors related to the parsing and usage of descriptors
+#[derive(Debug)]
+pub enum Error {
+    /// Invalid HD Key path, such as having a wildcard but a length != 1
+    InvalidHdKeyPath,
+    /// The provided descriptor doesn't match its checksum
+    InvalidDescriptorChecksum,
+    /// The descriptor contains hardened derivation steps on public extended keys
+    HardenedDerivationXpub,
+    /// The descriptor contains multipath keys
+    MultiPath,
+
+    /// Error thrown while working with [`keys`](crate::keys)
+    Key(crate::keys::KeyError),
+    /// Error while extracting and manipulating policies
+    Policy(crate::descriptor::policy::PolicyError),
+
+    /// Invalid byte found in the descriptor checksum
+    InvalidDescriptorCharacter(u8),
+
+    /// BIP32 error
+    Bip32(bitcoin::bip32::Error),
+    /// Error during base58 decoding
+    Base58(bitcoin::base58::Error),
+    /// Key-related error
+    Pk(bitcoin::key::Error),
+    /// Miniscript error
+    Miniscript(miniscript::Error),
+    /// Hex decoding error
+    Hex(bitcoin::hex::HexToBytesError),
+}
+
+impl From<crate::keys::KeyError> for Error {
+    fn from(key_error: crate::keys::KeyError) -> Error {
+        match key_error {
+            crate::keys::KeyError::Miniscript(inner) => Error::Miniscript(inner),
+            crate::keys::KeyError::Bip32(inner) => Error::Bip32(inner),
+            e => Error::Key(e),
+        }
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::InvalidHdKeyPath => write!(f, "Invalid HD key path"),
+            Self::InvalidDescriptorChecksum => {
+                write!(f, "The provided descriptor doesn't match its checksum")
+            }
+            Self::HardenedDerivationXpub => write!(
+                f,
+                "The descriptor contains hardened derivation steps on public extended keys"
+            ),
+            Self::MultiPath => write!(
+                f,
+                "The descriptor contains multipath keys, which are not supported yet"
+            ),
+            Self::Key(err) => write!(f, "Key error: {}", err),
+            Self::Policy(err) => write!(f, "Policy error: {}", err),
+            Self::InvalidDescriptorCharacter(char) => {
+                write!(f, "Invalid descriptor character: {}", char)
+            }
+            Self::Bip32(err) => write!(f, "BIP32 error: {}", err),
+            Self::Base58(err) => write!(f, "Base58 error: {}", err),
+            Self::Pk(err) => write!(f, "Key-related error: {}", err),
+            Self::Miniscript(err) => write!(f, "Miniscript error: {}", err),
+            Self::Hex(err) => write!(f, "Hex decoding error: {}", err),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for Error {}
+
+impl From<bitcoin::bip32::Error> for Error {
+    fn from(err: bitcoin::bip32::Error) -> Self {
+        Error::Bip32(err)
+    }
+}
+
+impl From<bitcoin::base58::Error> for Error {
+    fn from(err: bitcoin::base58::Error) -> Self {
+        Error::Base58(err)
+    }
+}
+
+impl From<bitcoin::key::Error> for Error {
+    fn from(err: bitcoin::key::Error) -> Self {
+        Error::Pk(err)
+    }
+}
+
+impl From<miniscript::Error> for Error {
+    fn from(err: miniscript::Error) -> Self {
+        Error::Miniscript(err)
+    }
+}
+
+impl From<bitcoin::hex::HexToBytesError> for Error {
+    fn from(err: bitcoin::hex::HexToBytesError) -> Self {
+        Error::Hex(err)
+    }
+}
+
+impl From<crate::descriptor::policy::PolicyError> for Error {
+    fn from(err: crate::descriptor::policy::PolicyError) -> Self {
+        Error::Policy(err)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/mod.rs.html new file mode 100644 index 0000000000..7ede089694 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/mod.rs.html @@ -0,0 +1,1803 @@ +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
+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
+
// 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.
+
+//! Descriptors
+//!
+//! This module contains generic utilities to work with descriptors, plus some re-exported types
+//! from [`miniscript`].
+
+use crate::collections::BTreeMap;
+use alloc::string::String;
+use alloc::vec::Vec;
+
+use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, KeySource, Xpub};
+use bitcoin::{key::XOnlyPublicKey, secp256k1, PublicKey};
+use bitcoin::{psbt, taproot};
+use bitcoin::{Network, TxOut};
+
+use miniscript::descriptor::{
+    DefiniteDescriptorKey, DescriptorMultiXKey, DescriptorSecretKey, DescriptorType,
+    DescriptorXKey, InnerXKey, KeyMap, SinglePubKey, Wildcard,
+};
+pub use miniscript::{
+    Descriptor, DescriptorPublicKey, Legacy, Miniscript, ScriptContext, Segwitv0,
+};
+use miniscript::{ForEachKey, MiniscriptKey, TranslatePk};
+
+use crate::descriptor::policy::BuildSatisfaction;
+
+pub mod checksum;
+#[doc(hidden)]
+pub mod dsl;
+pub mod error;
+pub mod policy;
+pub mod template;
+
+pub use self::checksum::calc_checksum;
+use self::checksum::calc_checksum_bytes;
+pub use self::error::Error as DescriptorError;
+pub use self::policy::Policy;
+use self::template::DescriptorTemplateOut;
+use crate::keys::{IntoDescriptorKey, KeyError};
+use crate::wallet::signer::SignersContainer;
+use crate::wallet::utils::SecpCtx;
+
+/// Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]
+pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
+
+/// Alias for a [`Descriptor`] that contains extended **derived** keys
+pub type DerivedDescriptor = Descriptor<DefiniteDescriptorKey>;
+
+/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
+/// [`psbt::Output`]
+///
+/// [`psbt::Input`]: bitcoin::psbt::Input
+/// [`psbt::Output`]: bitcoin::psbt::Output
+pub type HdKeyPaths = BTreeMap<secp256k1::PublicKey, KeySource>;
+
+/// Alias for the type of maps that represent taproot key origins in a [`psbt::Input`] or
+/// [`psbt::Output`]
+///
+/// [`psbt::Input`]: bitcoin::psbt::Input
+/// [`psbt::Output`]: bitcoin::psbt::Output
+pub type TapKeyOrigins = BTreeMap<XOnlyPublicKey, (Vec<taproot::TapLeafHash>, KeySource)>;
+
+/// Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]
+pub trait IntoWalletDescriptor {
+    /// Convert to wallet descriptor
+    fn into_wallet_descriptor(
+        self,
+        secp: &SecpCtx,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError>;
+}
+
+impl IntoWalletDescriptor for &str {
+    fn into_wallet_descriptor(
+        self,
+        secp: &SecpCtx,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
+        let descriptor = match self.split_once('#') {
+            Some((desc, original_checksum)) => {
+                let checksum = calc_checksum_bytes(desc)?;
+                if original_checksum.as_bytes() != checksum {
+                    return Err(DescriptorError::InvalidDescriptorChecksum);
+                }
+                desc
+            }
+            None => self,
+        };
+
+        ExtendedDescriptor::parse_descriptor(secp, descriptor)?
+            .into_wallet_descriptor(secp, network)
+    }
+}
+
+impl IntoWalletDescriptor for &String {
+    fn into_wallet_descriptor(
+        self,
+        secp: &SecpCtx,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
+        self.as_str().into_wallet_descriptor(secp, network)
+    }
+}
+
+impl IntoWalletDescriptor for ExtendedDescriptor {
+    fn into_wallet_descriptor(
+        self,
+        secp: &SecpCtx,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
+        (self, KeyMap::default()).into_wallet_descriptor(secp, network)
+    }
+}
+
+impl IntoWalletDescriptor for (ExtendedDescriptor, KeyMap) {
+    fn into_wallet_descriptor(
+        self,
+        secp: &SecpCtx,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
+        use crate::keys::DescriptorKey;
+
+        struct Translator<'s, 'd> {
+            secp: &'s SecpCtx,
+            descriptor: &'d ExtendedDescriptor,
+            network: Network,
+        }
+
+        impl<'s, 'd> miniscript::Translator<DescriptorPublicKey, String, DescriptorError>
+            for Translator<'s, 'd>
+        {
+            fn pk(&mut self, pk: &DescriptorPublicKey) -> Result<String, DescriptorError> {
+                let secp = &self.secp;
+
+                let (_, _, networks) = if self.descriptor.is_taproot() {
+                    let descriptor_key: DescriptorKey<miniscript::Tap> =
+                        pk.clone().into_descriptor_key()?;
+                    descriptor_key.extract(secp)?
+                } else if self.descriptor.is_witness() {
+                    let descriptor_key: DescriptorKey<miniscript::Segwitv0> =
+                        pk.clone().into_descriptor_key()?;
+                    descriptor_key.extract(secp)?
+                } else {
+                    let descriptor_key: DescriptorKey<miniscript::Legacy> =
+                        pk.clone().into_descriptor_key()?;
+                    descriptor_key.extract(secp)?
+                };
+
+                if networks.contains(&self.network) {
+                    Ok(Default::default())
+                } else {
+                    Err(DescriptorError::Key(KeyError::InvalidNetwork))
+                }
+            }
+            fn sha256(
+                &mut self,
+                _sha256: &<DescriptorPublicKey as MiniscriptKey>::Sha256,
+            ) -> Result<String, DescriptorError> {
+                Ok(Default::default())
+            }
+            fn hash256(
+                &mut self,
+                _hash256: &<DescriptorPublicKey as MiniscriptKey>::Hash256,
+            ) -> Result<String, DescriptorError> {
+                Ok(Default::default())
+            }
+            fn ripemd160(
+                &mut self,
+                _ripemd160: &<DescriptorPublicKey as MiniscriptKey>::Ripemd160,
+            ) -> Result<String, DescriptorError> {
+                Ok(Default::default())
+            }
+            fn hash160(
+                &mut self,
+                _hash160: &<DescriptorPublicKey as MiniscriptKey>::Hash160,
+            ) -> Result<String, DescriptorError> {
+                Ok(Default::default())
+            }
+        }
+
+        // check the network for the keys
+        use miniscript::TranslateErr;
+        match self.0.translate_pk(&mut Translator {
+            secp,
+            network,
+            descriptor: &self.0,
+        }) {
+            Ok(_) => {}
+            Err(TranslateErr::TranslatorErr(e)) => return Err(e),
+            Err(TranslateErr::OuterError(e)) => return Err(e.into()),
+        }
+
+        Ok(self)
+    }
+}
+
+impl IntoWalletDescriptor for DescriptorTemplateOut {
+    fn into_wallet_descriptor(
+        self,
+        _secp: &SecpCtx,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
+        struct Translator {
+            network: Network,
+        }
+
+        impl miniscript::Translator<DescriptorPublicKey, DescriptorPublicKey, DescriptorError>
+            for Translator
+        {
+            fn pk(
+                &mut self,
+                pk: &DescriptorPublicKey,
+            ) -> Result<DescriptorPublicKey, DescriptorError> {
+                // workaround for xpubs generated by other key types, like bip39: since when the
+                // conversion is made one network has to be chosen, what we generally choose
+                // "mainnet", but then override the set of valid networks to specify that all of
+                // them are valid. here we reset the network to make sure the wallet struct gets a
+                // descriptor with the right network everywhere.
+                let pk = match pk {
+                    DescriptorPublicKey::XPub(ref xpub) => {
+                        let mut xpub = xpub.clone();
+                        xpub.xkey.network = self.network;
+
+                        DescriptorPublicKey::XPub(xpub)
+                    }
+                    other => other.clone(),
+                };
+
+                Ok(pk)
+            }
+            miniscript::translate_hash_clone!(
+                DescriptorPublicKey,
+                DescriptorPublicKey,
+                DescriptorError
+            );
+        }
+
+        let (desc, keymap, networks) = self;
+
+        if !networks.contains(&network) {
+            return Err(DescriptorError::Key(KeyError::InvalidNetwork));
+        }
+
+        // fixup the network for keys that need it in the descriptor
+        use miniscript::TranslateErr;
+        let translated = match desc.translate_pk(&mut Translator { network }) {
+            Ok(descriptor) => descriptor,
+            Err(TranslateErr::TranslatorErr(e)) => return Err(e),
+            Err(TranslateErr::OuterError(e)) => return Err(e.into()),
+        };
+        // ...and in the key map
+        let fixed_keymap = keymap
+            .into_iter()
+            .map(|(mut k, mut v)| {
+                match (&mut k, &mut v) {
+                    (DescriptorPublicKey::XPub(xpub), DescriptorSecretKey::XPrv(xprv)) => {
+                        xpub.xkey.network = network;
+                        xprv.xkey.network = network;
+                    }
+                    (_, DescriptorSecretKey::Single(key)) => {
+                        key.key.network = network;
+                    }
+                    _ => {}
+                }
+
+                (k, v)
+            })
+            .collect();
+
+        Ok((translated, fixed_keymap))
+    }
+}
+
+/// Wrapper for `IntoWalletDescriptor` that performs additional checks on the keys contained in the
+/// descriptor
+pub(crate) fn into_wallet_descriptor_checked<T: IntoWalletDescriptor>(
+    inner: T,
+    secp: &SecpCtx,
+    network: Network,
+) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
+    let (descriptor, keymap) = inner.into_wallet_descriptor(secp, network)?;
+
+    // Ensure the keys don't contain any hardened derivation steps or hardened wildcards
+    let descriptor_contains_hardened_steps = descriptor.for_any_key(|k| {
+        if let DescriptorPublicKey::XPub(DescriptorXKey {
+            derivation_path,
+            wildcard,
+            ..
+        }) = k
+        {
+            return *wildcard == Wildcard::Hardened
+                || derivation_path.into_iter().any(ChildNumber::is_hardened);
+        }
+
+        false
+    });
+    if descriptor_contains_hardened_steps {
+        return Err(DescriptorError::HardenedDerivationXpub);
+    }
+
+    if descriptor.is_multipath() {
+        return Err(DescriptorError::MultiPath);
+    }
+
+    // Run miniscript's sanity check, which will look for duplicated keys and other potential
+    // issues
+    descriptor.sanity_check()?;
+
+    Ok((descriptor, keymap))
+}
+
+#[doc(hidden)]
+/// Used internally mainly by the `descriptor!()` and `fragment!()` macros
+pub trait CheckMiniscript<Ctx: miniscript::ScriptContext> {
+    fn check_miniscript(&self) -> Result<(), miniscript::Error>;
+}
+
+impl<Ctx: miniscript::ScriptContext, Pk: miniscript::MiniscriptKey> CheckMiniscript<Ctx>
+    for miniscript::Miniscript<Pk, Ctx>
+{
+    fn check_miniscript(&self) -> Result<(), miniscript::Error> {
+        Ctx::check_global_validity(self)?;
+
+        Ok(())
+    }
+}
+
+/// Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]
+pub trait ExtractPolicy {
+    /// Extract the spending [`policy`]
+    fn extract_policy(
+        &self,
+        signers: &SignersContainer,
+        psbt: BuildSatisfaction,
+        secp: &SecpCtx,
+    ) -> Result<Option<Policy>, DescriptorError>;
+}
+
+pub(crate) trait XKeyUtils {
+    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint;
+}
+
+impl<T> XKeyUtils for DescriptorMultiXKey<T>
+where
+    T: InnerXKey,
+{
+    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint {
+        match self.origin {
+            Some((fingerprint, _)) => fingerprint,
+            None => self.xkey.xkey_fingerprint(secp),
+        }
+    }
+}
+
+impl<T> XKeyUtils for DescriptorXKey<T>
+where
+    T: InnerXKey,
+{
+    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint {
+        match self.origin {
+            Some((fingerprint, _)) => fingerprint,
+            None => self.xkey.xkey_fingerprint(secp),
+        }
+    }
+}
+
+pub(crate) trait DescriptorMeta {
+    fn is_witness(&self) -> bool;
+    fn is_taproot(&self) -> bool;
+    fn get_extended_keys(&self) -> Vec<DescriptorXKey<Xpub>>;
+    fn derive_from_hd_keypaths(
+        &self,
+        hd_keypaths: &HdKeyPaths,
+        secp: &SecpCtx,
+    ) -> Option<DerivedDescriptor>;
+    fn derive_from_tap_key_origins(
+        &self,
+        tap_key_origins: &TapKeyOrigins,
+        secp: &SecpCtx,
+    ) -> Option<DerivedDescriptor>;
+    fn derive_from_psbt_key_origins(
+        &self,
+        key_origins: BTreeMap<Fingerprint, (&DerivationPath, SinglePubKey)>,
+        secp: &SecpCtx,
+    ) -> Option<DerivedDescriptor>;
+    fn derive_from_psbt_input(
+        &self,
+        psbt_input: &psbt::Input,
+        utxo: Option<TxOut>,
+        secp: &SecpCtx,
+    ) -> Option<DerivedDescriptor>;
+}
+
+impl DescriptorMeta for ExtendedDescriptor {
+    fn is_witness(&self) -> bool {
+        matches!(
+            self.desc_type(),
+            DescriptorType::Wpkh
+                | DescriptorType::ShWpkh
+                | DescriptorType::Wsh
+                | DescriptorType::ShWsh
+                | DescriptorType::ShWshSortedMulti
+                | DescriptorType::WshSortedMulti
+        )
+    }
+
+    fn is_taproot(&self) -> bool {
+        self.desc_type() == DescriptorType::Tr
+    }
+
+    fn get_extended_keys(&self) -> Vec<DescriptorXKey<Xpub>> {
+        let mut answer = Vec::new();
+
+        self.for_each_key(|pk| {
+            if let DescriptorPublicKey::XPub(xpub) = pk {
+                answer.push(xpub.clone());
+            }
+
+            true
+        });
+
+        answer
+    }
+
+    fn derive_from_psbt_key_origins(
+        &self,
+        key_origins: BTreeMap<Fingerprint, (&DerivationPath, SinglePubKey)>,
+        secp: &SecpCtx,
+    ) -> Option<DerivedDescriptor> {
+        // Ensure that deriving `xpub` with `path` yields `expected`
+        let verify_key =
+            |xpub: &DescriptorXKey<Xpub>, path: &DerivationPath, expected: &SinglePubKey| {
+                let derived = xpub
+                    .xkey
+                    .derive_pub(secp, path)
+                    .expect("The path should never contain hardened derivation steps")
+                    .public_key;
+
+                match expected {
+                    SinglePubKey::FullKey(pk) if &PublicKey::new(derived) == pk => true,
+                    SinglePubKey::XOnly(pk) if &XOnlyPublicKey::from(derived) == pk => true,
+                    _ => false,
+                }
+            };
+
+        let mut path_found = None;
+
+        // using `for_any_key` should make this stop as soon as we return `true`
+        self.for_any_key(|key| {
+            if let DescriptorPublicKey::XPub(xpub) = key {
+                // Check if the key matches one entry in our `key_origins`. If it does, `matches()` will
+                // return the "prefix" that matched, so we remove that prefix from the full path
+                // found in `key_origins` and save it in `derive_path`. We expect this to be a derivation
+                // path of length 1 if the key is `wildcard` and an empty path otherwise.
+                let root_fingerprint = xpub.root_fingerprint(secp);
+                let derive_path = key_origins
+                    .get_key_value(&root_fingerprint)
+                    .and_then(|(fingerprint, (path, expected))| {
+                        xpub.matches(&(*fingerprint, (*path).clone()), secp)
+                            .zip(Some((path, expected)))
+                    })
+                    .and_then(|(prefix, (full_path, expected))| {
+                        let derive_path = full_path
+                            .into_iter()
+                            .skip(prefix.into_iter().count())
+                            .cloned()
+                            .collect::<DerivationPath>();
+
+                        // `derive_path` only contains the replacement index for the wildcard, if present, or
+                        // an empty path for fixed descriptors. To verify the key we also need the normal steps
+                        // that come before the wildcard, so we take them directly from `xpub` and then append
+                        // the final index
+                        if verify_key(
+                            xpub,
+                            &xpub.derivation_path.extend(derive_path.clone()),
+                            expected,
+                        ) {
+                            Some(derive_path)
+                        } else {
+                            None
+                        }
+                    });
+
+                match derive_path {
+                    Some(path) if xpub.wildcard != Wildcard::None && path.len() == 1 => {
+                        // Ignore hardened wildcards
+                        if let ChildNumber::Normal { index } = path[0] {
+                            path_found = Some(index);
+                            return true;
+                        }
+                    }
+                    Some(path) if xpub.wildcard == Wildcard::None && path.is_empty() => {
+                        path_found = Some(0);
+                        return true;
+                    }
+                    _ => {}
+                }
+            }
+
+            false
+        });
+
+        path_found.map(|path| {
+            self.at_derivation_index(path)
+                .expect("We ignore hardened wildcards")
+        })
+    }
+
+    fn derive_from_hd_keypaths(
+        &self,
+        hd_keypaths: &HdKeyPaths,
+        secp: &SecpCtx,
+    ) -> Option<DerivedDescriptor> {
+        // "Convert" an hd_keypaths map to the format required by `derive_from_psbt_key_origins`
+        let key_origins = hd_keypaths
+            .iter()
+            .map(|(pk, (fingerprint, path))| {
+                (
+                    *fingerprint,
+                    (path, SinglePubKey::FullKey(PublicKey::new(*pk))),
+                )
+            })
+            .collect();
+        self.derive_from_psbt_key_origins(key_origins, secp)
+    }
+
+    fn derive_from_tap_key_origins(
+        &self,
+        tap_key_origins: &TapKeyOrigins,
+        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
+            .iter()
+            .map(|(pk, (_, (fingerprint, path)))| (*fingerprint, (path, SinglePubKey::XOnly(*pk))))
+            .collect();
+        self.derive_from_psbt_key_origins(key_origins, secp)
+    }
+
+    fn derive_from_psbt_input(
+        &self,
+        psbt_input: &psbt::Input,
+        utxo: Option<TxOut>,
+        secp: &SecpCtx,
+    ) -> Option<DerivedDescriptor> {
+        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.bip32_derivation, secp) {
+            return Some(derived);
+        }
+        if let Some(derived) = self.derive_from_tap_key_origins(&psbt_input.tap_key_origins, secp) {
+            return Some(derived);
+        }
+        if self.has_wildcard() {
+            // We can't try to bruteforce the derivation index, exit here
+            return None;
+        }
+
+        let descriptor = self.at_derivation_index(0).expect("0 is not hardened");
+        match descriptor.desc_type() {
+            // TODO: add pk() here
+            DescriptorType::Pkh
+            | DescriptorType::Wpkh
+            | DescriptorType::ShWpkh
+            | DescriptorType::Tr
+                if utxo.is_some()
+                    && descriptor.script_pubkey() == utxo.as_ref().unwrap().script_pubkey =>
+            {
+                Some(descriptor)
+            }
+            DescriptorType::Bare | DescriptorType::Sh | DescriptorType::ShSortedMulti
+                if psbt_input.redeem_script.is_some()
+                    && &descriptor.explicit_script().unwrap()
+                        == psbt_input.redeem_script.as_ref().unwrap() =>
+            {
+                Some(descriptor)
+            }
+            DescriptorType::Wsh
+            | DescriptorType::ShWsh
+            | DescriptorType::ShWshSortedMulti
+            | DescriptorType::WshSortedMulti
+                if psbt_input.witness_script.is_some()
+                    && &descriptor.explicit_script().unwrap()
+                        == psbt_input.witness_script.as_ref().unwrap() =>
+            {
+                Some(descriptor)
+            }
+            _ => None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use alloc::string::ToString;
+    use core::str::FromStr;
+
+    use assert_matches::assert_matches;
+    use bitcoin::hex::FromHex;
+    use bitcoin::secp256k1::Secp256k1;
+    use bitcoin::ScriptBuf;
+    use bitcoin::{bip32, Psbt};
+
+    use super::*;
+    use crate::psbt::PsbtUtils;
+
+    #[test]
+    fn test_derive_from_psbt_input_wpkh_wif() {
+        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
+            "wpkh(02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737)",
+        )
+        .unwrap();
+        let psbt = Psbt::deserialize(
+            &Vec::<u8>::from_hex(
+                "70736274ff010052010000000162307be8e431fbaff807cdf9cdc3fde44d7402\
+                 11bc8342c31ffd6ec11fe35bcc0100000000ffffffff01328601000000000016\
+                 001493ce48570b55c42c2af816aeaba06cfee1224fae000000000001011fa086\
+                 01000000000016001493ce48570b55c42c2af816aeaba06cfee1224fae010304\
+                 010000000000",
+            )
+            .unwrap(),
+        )
+        .unwrap();
+
+        assert!(descriptor
+            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0), &Secp256k1::new())
+            .is_some());
+    }
+
+    #[test]
+    fn test_derive_from_psbt_input_pkh_tpub() {
+        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
+            "pkh([0f056943/44h/0h/0h]tpubDDpWvmUrPZrhSPmUzCMBHffvC3HyMAPnWDSAQNBTnj1iZeJa7BZQEttFiP4DS4GCcXQHezdXhn86Hj6LHX5EDstXPWrMaSneRWM8yUf6NFd/10/*)",
+        )
+        .unwrap();
+        let psbt = Psbt::deserialize(
+            &Vec::<u8>::from_hex(
+                "70736274ff010053010000000145843b86be54a3cd8c9e38444e1162676c00df\
+                 e7964122a70df491ea12fd67090100000000ffffffff01c19598000000000017\
+                 a91432bb94283282f72b2e034709e348c44d5a4db0ef8700000000000100f902\
+                 0000000001010167e99c0eb67640f3a1b6805f2d8be8238c947f8aaf49eb0a9c\
+                 bee6a42c984200000000171600142b29a22019cca05b9c2b2d283a4c4489e1cf\
+                 9f8ffeffffff02a01dced06100000017a914e2abf033cadbd74f0f4c74946201\
+                 decd20d5c43c8780969800000000001976a9148b0fce5fb1264e599a65387313\
+                 3c95478b902eb288ac02473044022015d9211576163fa5b001e84dfa3d44efd9\
+                 86b8f3a0d3d2174369288b2b750906022048dacc0e5d73ae42512fd2b97e2071\
+                 a8d0bce443b390b1fe0b8128fe70ec919e01210232dad1c5a67dcb0116d407e2\
+                 52584228ab7ec00e8b9779d0c3ffe8114fc1a7d2c80600000103040100000022\
+                 0603433b83583f8c4879b329dd08bbc7da935e4cc02f637ff746e05f0466ffb2\
+                 a6a2180f0569432c00008000000080000000800a000000000000000000",
+            )
+            .unwrap(),
+        )
+        .unwrap();
+
+        assert!(descriptor
+            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0), &Secp256k1::new())
+            .is_some());
+    }
+
+    #[test]
+    fn test_derive_from_psbt_input_wsh() {
+        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
+            "wsh(and_v(v:pk(03b6633fef2397a0a9de9d7b6f23aef8368a6e362b0581f0f0af70d5ecfd254b14),older(6)))",
+        )
+        .unwrap();
+        let psbt = Psbt::deserialize(
+            &Vec::<u8>::from_hex(
+                "70736274ff01005302000000011c8116eea34408ab6529223c9a176606742207\
+                 67a1ff1d46a6e3c4a88243ea6e01000000000600000001109698000000000017\
+                 a914ad105f61102e0d01d7af40d06d6a5c3ae2f7fde387000000000001012b80\
+                 969800000000002200203ca72f106a72234754890ca7640c43f65d2174e44d33\
+                 336030f9059345091044010304010000000105252103b6633fef2397a0a9de9d\
+                 7b6f23aef8368a6e362b0581f0f0af70d5ecfd254b14ad56b20000",
+            )
+            .unwrap(),
+        )
+        .unwrap();
+
+        assert!(descriptor
+            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0), &Secp256k1::new())
+            .is_some());
+    }
+
+    #[test]
+    fn test_derive_from_psbt_input_sh() {
+        let descriptor = Descriptor::<DescriptorPublicKey>::from_str(
+            "sh(and_v(v:pk(021403881a5587297818fcaf17d239cefca22fce84a45b3b1d23e836c4af671dbb),after(630000)))",
+        )
+        .unwrap();
+        let psbt = Psbt::deserialize(
+            &Vec::<u8>::from_hex(
+                "70736274ff0100530100000001bc8c13df445dfadcc42afa6dc841f85d22b01d\
+                 a6270ebf981740f4b7b1d800390000000000feffffff01ba9598000000000017\
+                 a91457b148ba4d3e5fa8608a8657875124e3d1c9390887f09c0900000100e002\
+                 0000000001016ba1bbe05cc93574a0d611ec7d93ad0ab6685b28d0cd80e8a82d\
+                 debb326643c90100000000feffffff02809698000000000017a914d9a6e8c455\
+                 8e16c8253afe53ce37ad61cf4c38c487403504cf6100000017a9144044fb6e0b\
+                 757dfc1b34886b6a95aef4d3db137e870247304402202a9b72d939bcde8ba2a1\
+                 e0980597e47af4f5c152a78499143c3d0a78ac2286a602207a45b1df9e93b8c9\
+                 6f09f5c025fe3e413ca4b905fe65ee55d32a3276439a9b8f012102dc1fcc2636\
+                 4da1aa718f03d8d9bd6f2ff410ed2cf1245a168aa3bcc995ac18e0a806000001\
+                 03040100000001042821021403881a5587297818fcaf17d239cefca22fce84a4\
+                 5b3b1d23e836c4af671dbbad03f09c09b10000",
+            )
+            .unwrap(),
+        )
+        .unwrap();
+
+        assert!(descriptor
+            .derive_from_psbt_input(&psbt.inputs[0], psbt.get_utxo_for(0), &Secp256k1::new())
+            .is_some());
+    }
+
+    #[test]
+    fn test_to_wallet_descriptor_fixup_networks() {
+        use crate::keys::{any_network, IntoDescriptorKey};
+
+        let secp = Secp256k1::new();
+
+        let xprv = bip32::Xpriv::from_str("xprv9s21ZrQH143K3c3gF1DUWpWNr2SG2XrG8oYPpqYh7hoWsJy9NjabErnzriJPpnGHyKz5NgdXmq1KVbqS1r4NXdCoKitWg5e86zqXHa8kxyB").unwrap();
+        let path = bip32::DerivationPath::from_str("m/0").unwrap();
+
+        // here `to_descriptor_key` will set the valid networks for the key to only mainnet, since
+        // we are using an "xpub"
+        let key = (xprv, path.clone()).into_descriptor_key().unwrap();
+        // override it with any. this happens in some key conversions, like bip39
+        let key = key.override_valid_networks(any_network());
+
+        // make a descriptor out of it
+        let desc = crate::descriptor!(wpkh(key)).unwrap();
+        // this should convert the key that supports "any_network" to the right network (testnet)
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+
+        let mut xprv_testnet = xprv;
+        xprv_testnet.network = Network::Testnet;
+
+        let xpub_testnet = bip32::Xpub::from_priv(&secp, &xprv_testnet);
+        let desc_pubkey = DescriptorPublicKey::XPub(DescriptorXKey {
+            xkey: xpub_testnet,
+            origin: None,
+            derivation_path: path,
+            wildcard: Wildcard::Unhardened,
+        });
+
+        assert_eq!(wallet_desc.to_string(), "wpkh(tpubD6NzVbkrYhZ4XtJzoDja5snUjBNQRP5B3f4Hyn1T1x6PVPxzzVjvw6nJx2D8RBCxog9GEVjZoyStfepTz7TtKoBVdkCtnc7VCJh9dD4RAU9/0/*)#a3svx0ha");
+        assert_eq!(
+            keymap
+                .get(&desc_pubkey)
+                .map(|key| key.to_public(&secp).unwrap()),
+            Some(desc_pubkey)
+        );
+    }
+
+    // test IntoWalletDescriptor trait from &str with and without checksum appended
+    #[test]
+    fn test_descriptor_from_str_with_checksum() {
+        let secp = Secp256k1::new();
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc62"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)#67ju93jw"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert_matches!(desc, Err(DescriptorError::InvalidDescriptorChecksum));
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert_matches!(desc, Err(DescriptorError::InvalidDescriptorChecksum));
+    }
+
+    // test IntoWalletDescriptor trait from &str with keys from right and wrong network
+    #[test]
+    fn test_descriptor_from_str_with_keys_network() {
+        let secp = Secp256k1::new();
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
+            .into_wallet_descriptor(&secp, Network::Regtest);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
+            .into_wallet_descriptor(&secp, Network::Regtest);
+        assert!(desc.is_ok());
+
+        let desc = "sh(wpkh(02864bb4ad00cefa806098a69e192bbda937494e69eb452b87bb3f20f6283baedb))"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "sh(wpkh(02864bb4ad00cefa806098a69e192bbda937494e69eb452b87bb3f20f6283baedb))"
+            .into_wallet_descriptor(&secp, Network::Bitcoin);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
+            .into_wallet_descriptor(&secp, Network::Bitcoin);
+        assert_matches!(desc, Err(DescriptorError::Key(KeyError::InvalidNetwork)));
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
+            .into_wallet_descriptor(&secp, Network::Bitcoin);
+        assert_matches!(desc, Err(DescriptorError::Key(KeyError::InvalidNetwork)));
+    }
+
+    // test IntoWalletDescriptor trait from the output of the descriptor!() macro
+    #[test]
+    fn test_descriptor_from_str_from_output_of_macro() {
+        let secp = Secp256k1::new();
+
+        let tpub = bip32::Xpub::from_str("tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK").unwrap();
+        let path = bip32::DerivationPath::from_str("m/1/2").unwrap();
+        let key = (tpub, path).into_descriptor_key().unwrap();
+
+        // make a descriptor out of it
+        let desc = crate::descriptor!(wpkh(key)).unwrap();
+
+        let (wallet_desc, _) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let wallet_desc_str = wallet_desc.to_string();
+        assert_eq!(wallet_desc_str, "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)#67ju93jw");
+
+        let (wallet_desc2, _) = wallet_desc_str
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        assert_eq!(wallet_desc, wallet_desc2)
+    }
+
+    #[test]
+    fn test_into_wallet_descriptor_checked() {
+        let secp = Secp256k1::new();
+
+        let descriptor = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0'/1/2/*)";
+        let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
+
+        assert_matches!(result, Err(DescriptorError::HardenedDerivationXpub));
+
+        let descriptor = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/<0;1>/*)";
+        let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
+
+        assert_matches!(result, Err(DescriptorError::MultiPath));
+
+        // repeated pubkeys
+        let descriptor = "wsh(multi(2,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*))";
+        let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
+
+        assert!(result.is_err());
+    }
+
+    #[test]
+    fn test_sh_wsh_sortedmulti_redeemscript() {
+        use miniscript::psbt::PsbtInputExt;
+
+        let secp = Secp256k1::new();
+
+        let descriptor = "sh(wsh(sortedmulti(3,tpubDEsqS36T4DVsKJd9UH8pAKzrkGBYPLEt9jZMwpKtzh1G6mgYehfHt9WCgk7MJG5QGSFWf176KaBNoXbcuFcuadAFKxDpUdMDKGBha7bY3QM/0/*,tpubDF3cpwfs7fMvXXuoQbohXtLjNM6ehwYT287LWtmLsd4r77YLg6MZg4vTETx5MSJ2zkfigbYWu31VA2Z2Vc1cZugCYXgS7FQu6pE8V6TriEH/0/*,tpubDE1SKfcW76Tb2AASv5bQWMuScYNAdoqLHoexw13sNDXwmUhQDBbCD3QAedKGLhxMrWQdMDKENzYtnXPDRvexQPNuDrLj52wAjHhNEm8sJ4p/0/*,tpubDFLc6oXwJmhm3FGGzXkfJNTh2KitoY3WhmmQvuAjMhD8YbyWn5mAqckbxXfm2etM3p5J6JoTpSrMqRSTfMLtNW46poDaEZJ1kjd3csRSjwH/0/*,tpubDEWD9NBeWP59xXmdqSNt4VYdtTGwbpyP8WS962BuqpQeMZmX9Pur14dhXdZT5a7wR1pK6dPtZ9fP5WR493hPzemnBvkfLLYxnUjAKj1JCQV/0/*,tpubDEHyZkkwd7gZWCTgQuYQ9C4myF2hMEmyHsBCCmLssGqoqUxeT3gzohF5uEVURkf9TtmeepJgkSUmteac38FwZqirjApzNX59XSHLcwaTZCH/0/*,tpubDEqLouCekwnMUWN486kxGzD44qVgeyuqHyxUypNEiQt5RnUZNJe386TKPK99fqRV1vRkZjYAjtXGTECz98MCsdLcnkM67U6KdYRzVubeCgZ/0/*)))";
+        let (descriptor, _) =
+            into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet).unwrap();
+
+        let descriptor = descriptor.at_derivation_index(0).unwrap();
+
+        let script = ScriptBuf::from_hex("5321022f533b667e2ea3b36e21961c9fe9dca340fbe0af5210173a83ae0337ab20a57621026bb53a98e810bd0ee61a0ed1164ba6c024786d76554e793e202dc6ce9c78c4ea2102d5b8a7d66a41ffdb6f4c53d61994022e886b4f45001fb158b95c9164d45f8ca3210324b75eead2c1f9c60e8adeb5e7009fec7a29afcdb30d829d82d09562fe8bae8521032d34f8932200833487bd294aa219dcbe000b9f9b3d824799541430009f0fa55121037468f8ea99b6c64788398b5ad25480cad08f4b0d65be54ce3a55fd206b5ae4722103f72d3d96663b0ea99b0aeb0d7f273cab11a8de37885f1dddc8d9112adb87169357ae").unwrap();
+
+        let mut psbt_input = psbt::Input::default();
+        psbt_input
+            .update_with_descriptor_unchecked(&descriptor)
+            .unwrap();
+
+        assert_eq!(psbt_input.redeem_script, Some(script.to_p2wsh()));
+        assert_eq!(psbt_input.witness_script, Some(script));
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/policy.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/policy.rs.html new file mode 100644 index 0000000000..713d80ec25 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/policy.rs.html @@ -0,0 +1,3813 @@ +policy.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
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+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
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+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
+
// 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.
+
+//! 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.
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::sync::Arc;
+//! # use bdk_wallet::descriptor::*;
+//! # use bdk_wallet::wallet::signer::*;
+//! # use bdk_wallet::bitcoin::secp256k1::Secp256k1;
+//! use bdk_wallet::descriptor::policy::BuildSatisfaction;
+//! let secp = Secp256k1::new();
+//! let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
+//!
+//! let (extended_desc, key_map) = ExtendedDescriptor::parse_descriptor(&secp, desc)?;
+//! println!("{:?}", extended_desc);
+//!
+//! 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).unwrap());
+//! # Ok::<(), anyhow::Error>(())
+//! ```
+
+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};
+
+use bitcoin::bip32::Fingerprint;
+use bitcoin::hashes::{hash160, ripemd160, sha256};
+use bitcoin::{absolute, key::XOnlyPublicKey, PublicKey, Sequence};
+
+use miniscript::descriptor::{
+    DescriptorPublicKey, ShInner, SinglePub, SinglePubKey, SortedMultiVec, WshInner,
+};
+use miniscript::hash256;
+use miniscript::{
+    Descriptor, Miniscript, Satisfier, ScriptContext, SigType, Terminal, ToPublicKey,
+};
+
+use crate::descriptor::ExtractPolicy;
+use crate::keys::ExtScriptContext;
+use crate::wallet::signer::{SignerId, SignersContainer};
+use crate::wallet::utils::{After, Older, SecpCtx};
+
+use super::checksum::calc_checksum;
+use super::error::Error;
+use super::XKeyUtils;
+use bitcoin::psbt::{self, Psbt};
+use miniscript::psbt::PsbtInputSatisfier;
+
+/// A unique identifier for a key
+#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum PkOrF {
+    /// A legacy public key
+    Pubkey(PublicKey),
+    /// A x-only public key
+    XOnlyPubkey(XOnlyPublicKey),
+    /// An extended key fingerprint
+    Fingerprint(Fingerprint),
+}
+
+impl PkOrF {
+    fn from_key(k: &DescriptorPublicKey, secp: &SecpCtx) -> Self {
+        match k {
+            DescriptorPublicKey::Single(SinglePub {
+                key: SinglePubKey::FullKey(pk),
+                ..
+            }) => PkOrF::Pubkey(*pk),
+            DescriptorPublicKey::Single(SinglePub {
+                key: SinglePubKey::XOnly(pk),
+                ..
+            }) => PkOrF::XOnlyPubkey(*pk),
+            DescriptorPublicKey::XPub(xpub) => PkOrF::Fingerprint(xpub.root_fingerprint(secp)),
+            DescriptorPublicKey::MultiXPub(multi) => {
+                PkOrF::Fingerprint(multi.root_fingerprint(secp))
+            }
+        }
+    }
+}
+
+/// An item that needs to be satisfied
+#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
+#[serde(tag = "type", rename_all = "UPPERCASE")]
+pub enum SatisfiableItem {
+    // Leaves
+    /// ECDSA Signature for a raw public key
+    EcdsaSignature(PkOrF),
+    /// Schnorr Signature for a raw public key
+    SchnorrSignature(PkOrF),
+    /// SHA256 preimage hash
+    Sha256Preimage {
+        /// The digest value
+        hash: sha256::Hash,
+    },
+    /// Double SHA256 preimage hash
+    Hash256Preimage {
+        /// The digest value
+        hash: hash256::Hash,
+    },
+    /// RIPEMD160 preimage hash
+    Ripemd160Preimage {
+        /// The digest value
+        hash: ripemd160::Hash,
+    },
+    /// SHA256 then RIPEMD160 preimage hash
+    Hash160Preimage {
+        /// The digest value
+        hash: hash160::Hash,
+    },
+    /// Absolute timeclock timestamp
+    AbsoluteTimelock {
+        /// The timelock value
+        value: absolute::LockTime,
+    },
+    /// Relative timelock locktime
+    RelativeTimelock {
+        /// The timelock value
+        value: Sequence,
+    },
+    /// Multi-signature public keys with threshold count
+    Multisig {
+        /// The raw public key or extended key fingerprint
+        keys: Vec<PkOrF>,
+        /// The required threshold count
+        threshold: usize,
+    },
+
+    // Complex item
+    /// Threshold items with threshold count
+    Thresh {
+        /// The policy items
+        items: Vec<Policy>,
+        /// The required threshold count
+        threshold: usize,
+    },
+}
+
+impl SatisfiableItem {
+    /// Returns whether the [`SatisfiableItem`] is a leaf item
+    pub fn is_leaf(&self) -> bool {
+        !matches!(
+            self,
+            SatisfiableItem::Thresh {
+                items: _,
+                threshold: _,
+            }
+        )
+    }
+
+    /// Returns a unique id for the [`SatisfiableItem`]
+    pub fn id(&self) -> String {
+        calc_checksum(&serde_json::to_string(self).expect("Failed to serialize a SatisfiableItem"))
+            .expect("Failed to compute a SatisfiableItem id")
+    }
+}
+
+fn combinations(vec: &[usize], size: usize) -> Vec<Vec<usize>> {
+    assert!(vec.len() >= size);
+
+    let mut answer = Vec::new();
+
+    let mut queue = VecDeque::new();
+    for (index, val) in vec.iter().enumerate() {
+        let mut new_vec = Vec::with_capacity(size);
+        new_vec.push(*val);
+        queue.push_back((index, new_vec));
+    }
+
+    while let Some((index, vals)) = queue.pop_front() {
+        if vals.len() >= size {
+            answer.push(vals);
+        } else {
+            for (new_index, val) in vec.iter().skip(index + 1).enumerate() {
+                let mut cloned = vals.clone();
+                cloned.push(*val);
+                queue.push_front((new_index, cloned));
+            }
+        }
+    }
+
+    answer
+}
+
+fn mix<T: Clone>(vec: Vec<Vec<T>>) -> Vec<Vec<T>> {
+    if vec.is_empty() || vec.iter().any(Vec::is_empty) {
+        return vec![];
+    }
+
+    let mut answer = Vec::new();
+    let size = vec.len();
+
+    let mut queue = VecDeque::new();
+    for i in &vec[0] {
+        let mut new_vec = Vec::with_capacity(size);
+        new_vec.push(i.clone());
+        queue.push_back(new_vec);
+    }
+
+    while let Some(vals) = queue.pop_front() {
+        if vals.len() >= size {
+            answer.push(vals);
+        } else {
+            let level = vals.len();
+            for i in &vec[level] {
+                let mut cloned = vals.clone();
+                cloned.push(i.clone());
+                queue.push_front(cloned);
+            }
+        }
+    }
+
+    answer
+}
+
+/// Type for a map of sets of [`Condition`] items keyed by each set's index
+pub type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
+/// Type for a map of folded sets of [`Condition`] items keyed by a vector of the combined set's indexes
+pub type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
+
+fn serialize_folded_cond_map<S>(
+    input_map: &FoldedConditionMap,
+    serializer: S,
+) -> Result<S::Ok, S::Error>
+where
+    S: Serializer,
+{
+    let mut map = serializer.serialize_map(Some(input_map.len()))?;
+    for (k, v) in input_map {
+        let k_string = format!("{:?}", k);
+        map.serialize_entry(&k_string, v)?;
+    }
+    map.end()
+}
+
+/// Represent if and how much a policy item is satisfied by the wallet's descriptor
+#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
+#[serde(tag = "type", rename_all = "UPPERCASE")]
+pub enum Satisfaction {
+    /// Only a partial satisfaction of some kind of threshold policy
+    Partial {
+        /// Total number of items
+        n: usize,
+        /// Threshold
+        m: usize,
+        /// The items that can be satisfied by the descriptor or are satisfied in the PSBT
+        items: Vec<usize>,
+        #[serde(skip_serializing_if = "Option::is_none")]
+        /// Whether the items are sorted in lexicographic order (used by `sortedmulti`)
+        sorted: Option<bool>,
+        #[serde(skip_serializing_if = "BTreeMap::is_empty")]
+        /// Extra conditions that also need to be satisfied
+        conditions: ConditionMap,
+    },
+    /// Can reach the threshold of some kind of threshold policy
+    PartialComplete {
+        /// Total number of items
+        n: usize,
+        /// Threshold
+        m: usize,
+        /// The items that can be satisfied by the descriptor
+        items: Vec<usize>,
+        #[serde(skip_serializing_if = "Option::is_none")]
+        /// Whether the items are sorted in lexicographic order (used by `sortedmulti`)
+        sorted: Option<bool>,
+        #[serde(
+            serialize_with = "serialize_folded_cond_map",
+            skip_serializing_if = "BTreeMap::is_empty"
+        )]
+        /// Extra conditions that also need to be satisfied
+        conditions: FoldedConditionMap,
+    },
+
+    /// Can satisfy the policy item
+    Complete {
+        /// Extra conditions that also need to be satisfied
+        condition: Condition,
+    },
+    /// Cannot satisfy or contribute to the policy item
+    None,
+}
+
+impl Satisfaction {
+    /// Returns whether the [`Satisfaction`] is a leaf item
+    pub fn is_leaf(&self) -> bool {
+        match self {
+            Satisfaction::None | Satisfaction::Complete { .. } => true,
+            Satisfaction::PartialComplete { .. } | Satisfaction::Partial { .. } => false,
+        }
+    }
+
+    // add `inner` as one of self's partial items. this only makes sense on partials
+    fn add(&mut self, inner: &Satisfaction, inner_index: usize) -> Result<(), PolicyError> {
+        match self {
+            Satisfaction::None | Satisfaction::Complete { .. } => Err(PolicyError::AddOnLeaf),
+            Satisfaction::PartialComplete { .. } => Err(PolicyError::AddOnPartialComplete),
+            Satisfaction::Partial {
+                n,
+                ref mut conditions,
+                ref mut items,
+                ..
+            } => {
+                if inner_index >= *n || items.contains(&inner_index) {
+                    return Err(PolicyError::IndexOutOfRange(inner_index));
+                }
+
+                match inner {
+                    // not relevant if not completed yet
+                    Satisfaction::None | Satisfaction::Partial { .. } => return Ok(()),
+                    Satisfaction::Complete { condition } => {
+                        items.push(inner_index);
+                        conditions.insert(inner_index, vec![*condition].into_iter().collect());
+                    }
+                    Satisfaction::PartialComplete {
+                        conditions: other_conditions,
+                        ..
+                    } => {
+                        items.push(inner_index);
+                        let conditions_set = other_conditions
+                            .values()
+                            .fold(HashSet::new(), |set, i| set.union(i).cloned().collect());
+                        conditions.insert(inner_index, conditions_set);
+                    }
+                }
+
+                Ok(())
+            }
+        }
+    }
+
+    fn finalize(&mut self) {
+        // if partial try to bump it to a partialcomplete
+        if let Satisfaction::Partial {
+            n,
+            m,
+            items,
+            conditions,
+            sorted,
+        } = self
+        {
+            if items.len() >= *m {
+                let mut map = BTreeMap::new();
+                let indexes = combinations(items, *m);
+                // `indexes` at this point is a Vec<Vec<usize>>, with the "n choose k" of items (m of n)
+                indexes
+                    .into_iter()
+                    // .inspect(|x| println!("--- orig --- {:?}", x))
+                    // we map each of the combinations of elements into a tuple of ([chosen items], [conditions]). unfortunately, those items have potentially more than one
+                    // condition (think about ORs), so we also use `mix` to expand those, i.e. [[0], [1, 2]] becomes [[0, 1], [0, 2]]. This is necessary to make sure that we
+                    // consider every possible options and check whether or not they are compatible.
+                    // since this step can turn one item of the iterator into multiple ones, we use `flat_map()` to expand them out
+                    .flat_map(|i_vec| {
+                        mix(i_vec
+                            .iter()
+                            .map(|i| {
+                                conditions
+                                    .get(i)
+                                    .map(|set| set.clone().into_iter().collect())
+                                    .unwrap_or_default()
+                            })
+                            .collect())
+                        .into_iter()
+                        .map(|x| (i_vec.clone(), x))
+                        .collect::<Vec<(Vec<usize>, Vec<Condition>)>>()
+                    })
+                    // .inspect(|x| println!("flat {:?}", x))
+                    // try to fold all the conditions for this specific combination of indexes/options. if they are not compatible, try_fold will be Err
+                    .map(|(key, val)| {
+                        (
+                            key,
+                            val.into_iter()
+                                .try_fold(Condition::default(), |acc, v| acc.merge(&v)),
+                        )
+                    })
+                    // .inspect(|x| println!("try_fold {:?}", x))
+                    // filter out all the incompatible combinations
+                    .filter(|(_, val)| val.is_ok())
+                    // .inspect(|x| println!("filter {:?}", x))
+                    // push them into the map
+                    .for_each(|(key, val)| {
+                        map.entry(key)
+                            .or_insert_with(HashSet::new)
+                            .insert(val.unwrap());
+                    });
+                // TODO: if the map is empty, the conditions are not compatible, return an error?
+                *self = Satisfaction::PartialComplete {
+                    n: *n,
+                    m: *m,
+                    items: items.clone(),
+                    conditions: map,
+                    sorted: *sorted,
+                };
+            }
+        }
+    }
+}
+
+impl From<bool> for Satisfaction {
+    fn from(other: bool) -> Self {
+        if other {
+            Satisfaction::Complete {
+                condition: Default::default(),
+            }
+        } else {
+            Satisfaction::None
+        }
+    }
+}
+
+/// Descriptor spending policy
+#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
+pub struct Policy {
+    /// Identifier for this policy node
+    pub id: String,
+
+    /// Type of this policy node
+    #[serde(flatten)]
+    pub item: SatisfiableItem,
+    /// How much a given PSBT already satisfies this policy node in terms of signatures
+    pub satisfaction: Satisfaction,
+    /// How the wallet's descriptor can satisfy this policy node
+    pub contribution: Satisfaction,
+}
+
+/// An extra condition that must be satisfied but that is out of control of the user
+/// TODO: use `bitcoin::LockTime` and `bitcoin::Sequence`
+#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Default, Serialize)]
+pub struct Condition {
+    /// Optional CheckSequenceVerify condition
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub csv: Option<Sequence>,
+    /// Optional timelock condition
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub timelock: Option<absolute::LockTime>,
+}
+
+impl Condition {
+    fn merge_nlocktime(
+        a: absolute::LockTime,
+        b: absolute::LockTime,
+    ) -> Result<absolute::LockTime, PolicyError> {
+        if !a.is_same_unit(b) {
+            Err(PolicyError::MixedTimelockUnits)
+        } else if a > b {
+            Ok(a)
+        } else {
+            Ok(b)
+        }
+    }
+
+    fn merge_nsequence(a: Sequence, b: Sequence) -> Result<Sequence, PolicyError> {
+        if a.is_time_locked() != b.is_time_locked() {
+            Err(PolicyError::MixedTimelockUnits)
+        } else {
+            Ok(max(a, b))
+        }
+    }
+
+    pub(crate) fn merge(mut self, other: &Condition) -> Result<Self, PolicyError> {
+        match (self.csv, other.csv) {
+            (Some(a), Some(b)) => self.csv = Some(Self::merge_nsequence(a, b)?),
+            (None, any) => self.csv = any,
+            _ => {}
+        }
+
+        match (self.timelock, other.timelock) {
+            (Some(a), Some(b)) => self.timelock = Some(Self::merge_nlocktime(a, b)?),
+            (None, any) => self.timelock = any,
+            _ => {}
+        }
+
+        Ok(self)
+    }
+
+    /// Returns `true` if there are no extra conditions to verify
+    pub fn is_null(&self) -> bool {
+        self.csv.is_none() && self.timelock.is_none()
+    }
+}
+
+/// Errors that can happen while extracting and manipulating policies
+#[derive(Debug, PartialEq, Eq)]
+pub enum PolicyError {
+    /// Not enough items are selected to satisfy a [`SatisfiableItem::Thresh`] or a [`SatisfiableItem::Multisig`]
+    NotEnoughItemsSelected(String),
+    /// Index out of range for an item to satisfy a [`SatisfiableItem::Thresh`] or a [`SatisfiableItem::Multisig`]
+    IndexOutOfRange(usize),
+    /// Can not add to an item that is [`Satisfaction::None`] or [`Satisfaction::Complete`]
+    AddOnLeaf,
+    /// Can not add to an item that is [`Satisfaction::PartialComplete`]
+    AddOnPartialComplete,
+    /// Can not merge CSV or timelock values unless both are less than or both are equal or greater than 500_000_000
+    MixedTimelockUnits,
+    /// Incompatible conditions (not currently used)
+    IncompatibleConditions,
+}
+
+impl fmt::Display for PolicyError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::NotEnoughItemsSelected(err) => write!(f, "Not enough items selected: {}", err),
+            Self::IndexOutOfRange(index) => write!(f, "Index out of range: {}", index),
+            Self::AddOnLeaf => write!(f, "Add on leaf"),
+            Self::AddOnPartialComplete => write!(f, "Add on partial complete"),
+            Self::MixedTimelockUnits => write!(f, "Mixed timelock units"),
+            Self::IncompatibleConditions => write!(f, "Incompatible conditions"),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for PolicyError {}
+
+impl Policy {
+    fn new(item: SatisfiableItem) -> Self {
+        Policy {
+            id: item.id(),
+            item,
+            satisfaction: Satisfaction::None,
+            contribution: Satisfaction::None,
+        }
+    }
+
+    fn make_and(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
+        match (a, b) {
+            (None, None) => Ok(None),
+            (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
+            (Some(a), Some(b)) => Self::make_thresh(vec![a, b], 2),
+        }
+    }
+
+    fn make_or(a: Option<Policy>, b: Option<Policy>) -> Result<Option<Policy>, PolicyError> {
+        match (a, b) {
+            (None, None) => Ok(None),
+            (Some(x), None) | (None, Some(x)) => Ok(Some(x)),
+            (Some(a), Some(b)) => Self::make_thresh(vec![a, b], 1),
+        }
+    }
+
+    fn make_thresh(items: Vec<Policy>, threshold: usize) -> Result<Option<Policy>, PolicyError> {
+        if threshold == 0 {
+            return Ok(None);
+        }
+
+        let mut contribution = Satisfaction::Partial {
+            n: items.len(),
+            m: threshold,
+            items: vec![],
+            conditions: Default::default(),
+            sorted: None,
+        };
+        let mut satisfaction = contribution.clone();
+        for (index, item) in items.iter().enumerate() {
+            contribution.add(&item.contribution, index)?;
+            satisfaction.add(&item.satisfaction, index)?;
+        }
+
+        contribution.finalize();
+        satisfaction.finalize();
+
+        let mut policy: Policy = SatisfiableItem::Thresh { items, threshold }.into();
+        policy.contribution = contribution;
+        policy.satisfaction = satisfaction;
+
+        Ok(Some(policy))
+    }
+
+    fn make_multisig<Ctx: ScriptContext + 'static>(
+        keys: &[DescriptorPublicKey],
+        signers: &SignersContainer,
+        build_sat: BuildSatisfaction,
+        threshold: usize,
+        sorted: bool,
+        secp: &SecpCtx,
+    ) -> Result<Option<Policy>, PolicyError> {
+        if threshold == 0 {
+            return Ok(None);
+        }
+
+        let parsed_keys = keys.iter().map(|k| PkOrF::from_key(k, secp)).collect();
+
+        let mut contribution = Satisfaction::Partial {
+            n: keys.len(),
+            m: threshold,
+            items: vec![],
+            conditions: Default::default(),
+            sorted: Some(sorted),
+        };
+        let mut satisfaction = contribution.clone();
+
+        for (index, key) in keys.iter().enumerate() {
+            if signers.find(signer_id(key, secp)).is_some() {
+                contribution.add(
+                    &Satisfaction::Complete {
+                        condition: Default::default(),
+                    },
+                    index,
+                )?;
+            }
+
+            if let Some(psbt) = build_sat.psbt() {
+                if Ctx::find_signature(psbt, key, secp) {
+                    satisfaction.add(
+                        &Satisfaction::Complete {
+                            condition: Default::default(),
+                        },
+                        index,
+                    )?;
+                }
+            }
+        }
+        satisfaction.finalize();
+        contribution.finalize();
+
+        let mut policy: Policy = SatisfiableItem::Multisig {
+            keys: parsed_keys,
+            threshold,
+        }
+        .into();
+        policy.contribution = contribution;
+        policy.satisfaction = satisfaction;
+
+        Ok(Some(policy))
+    }
+
+    /// 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.
+    pub fn requires_path(&self) -> bool {
+        self.get_condition(&BTreeMap::new()).is_err()
+    }
+
+    /// Return the conditions that are set by the spending policy for a given path in the
+    /// policy tree
+    pub fn get_condition(
+        &self,
+        path: &BTreeMap<String, Vec<usize>>,
+    ) -> Result<Condition, PolicyError> {
+        // if items.len() == threshold, selected can be omitted and we take all of them by default
+        let default = match &self.item {
+            SatisfiableItem::Thresh { items, threshold } if items.len() == *threshold => {
+                (0..*threshold).collect()
+            }
+            SatisfiableItem::Multisig { keys, .. } => (0..keys.len()).collect(),
+            _ => HashSet::new(),
+        };
+        let selected: HashSet<_> = match path.get(&self.id) {
+            Some(arr) => arr.iter().copied().collect(),
+            _ => default,
+        };
+
+        match &self.item {
+            SatisfiableItem::Thresh { items, threshold } => {
+                let mapped_req = items
+                    .iter()
+                    .map(|i| i.get_condition(path))
+                    .collect::<Vec<_>>();
+
+                // if all the requirements are null we don't care about `selected` because there
+                // are no requirements
+                if mapped_req
+                    .iter()
+                    .all(|cond| matches!(cond, Ok(c) if c.is_null()))
+                {
+                    return Ok(Condition::default());
+                }
+
+                // make sure all the indexes in the `selected` list are within range
+                for index in &selected {
+                    if *index >= items.len() {
+                        return Err(PolicyError::IndexOutOfRange(*index));
+                    }
+                }
+
+                // if we have something, make sure we have enough items. note that the user can set
+                // an empty value for this step in case of n-of-n, because `selected` is set to all
+                // the elements above
+                if selected.len() < *threshold {
+                    return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()));
+                }
+
+                // check the selected items, see if there are conflicting requirements
+                mapped_req
+                    .into_iter()
+                    .enumerate()
+                    .filter(|(index, _)| selected.contains(index))
+                    .try_fold(Condition::default(), |acc, (_, cond)| acc.merge(&cond?))
+            }
+            SatisfiableItem::Multisig { keys, threshold } => {
+                if selected.len() < *threshold {
+                    return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()));
+                }
+                if let Some(item) = selected.into_iter().find(|&i| i >= keys.len()) {
+                    return Err(PolicyError::IndexOutOfRange(item));
+                }
+
+                Ok(Condition::default())
+            }
+            SatisfiableItem::AbsoluteTimelock { value } => Ok(Condition {
+                csv: None,
+                timelock: Some(*value),
+            }),
+            SatisfiableItem::RelativeTimelock { value } => Ok(Condition {
+                csv: Some(*value),
+                timelock: None,
+            }),
+            _ => Ok(Condition::default()),
+        }
+    }
+}
+
+impl From<SatisfiableItem> for Policy {
+    fn from(other: SatisfiableItem) -> Self {
+        Self::new(other)
+    }
+}
+
+fn signer_id(key: &DescriptorPublicKey, secp: &SecpCtx) -> SignerId {
+    // For consistency we always compute the key hash in "ecdsa" form (with the leading sign
+    // prefix) even if we are in a taproot descriptor. We just want some kind of unique identifier
+    // for a key, so it doesn't really matter how the identifier is computed.
+    match key {
+        DescriptorPublicKey::Single(SinglePub {
+            key: SinglePubKey::FullKey(pk),
+            ..
+        }) => pk.to_pubkeyhash(SigType::Ecdsa).into(),
+        DescriptorPublicKey::Single(SinglePub {
+            key: SinglePubKey::XOnly(pk),
+            ..
+        }) => pk.to_pubkeyhash(SigType::Ecdsa).into(),
+        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint(secp).into(),
+        DescriptorPublicKey::MultiXPub(xpub) => xpub.root_fingerprint(secp).into(),
+    }
+}
+
+fn make_generic_signature<M: Fn() -> SatisfiableItem, F: Fn(&Psbt) -> bool>(
+    key: &DescriptorPublicKey,
+    signers: &SignersContainer,
+    build_sat: BuildSatisfaction,
+    secp: &SecpCtx,
+    make_policy: M,
+    find_sig: F,
+) -> Policy {
+    let mut policy: Policy = make_policy().into();
+
+    policy.contribution = if signers.find(signer_id(key, secp)).is_some() {
+        Satisfaction::Complete {
+            condition: Default::default(),
+        }
+    } else {
+        Satisfaction::None
+    };
+
+    if let Some(psbt) = build_sat.psbt() {
+        policy.satisfaction = if find_sig(psbt) {
+            Satisfaction::Complete {
+                condition: Default::default(),
+            }
+        } else {
+            Satisfaction::None
+        };
+    }
+
+    policy
+}
+
+fn generic_sig_in_psbt<
+    // C is for "check", it's a closure we use to *check* if a psbt input contains the signature
+    // for a specific key
+    C: Fn(&psbt::Input, &SinglePubKey) -> bool,
+    // E is for "extract", it extracts a key from the bip32 derivations found in the psbt input
+    E: Fn(&psbt::Input, Fingerprint) -> Option<SinglePubKey>,
+>(
+    psbt: &Psbt,
+    key: &DescriptorPublicKey,
+    secp: &SecpCtx,
+    check: C,
+    extract: E,
+) -> bool {
+    //TODO check signature validity
+    psbt.inputs.iter().all(|input| match key {
+        DescriptorPublicKey::Single(SinglePub { key, .. }) => check(input, key),
+        DescriptorPublicKey::XPub(xpub) => {
+            //TODO check actual derivation matches
+            match extract(input, xpub.root_fingerprint(secp)) {
+                Some(pubkey) => check(input, &pubkey),
+                None => false,
+            }
+        }
+        DescriptorPublicKey::MultiXPub(xpub) => {
+            //TODO check actual derivation matches
+            match extract(input, xpub.root_fingerprint(secp)) {
+                Some(pubkey) => check(input, &pubkey),
+                None => false,
+            }
+        }
+    })
+}
+
+trait SigExt: ScriptContext {
+    fn make_signature(
+        key: &DescriptorPublicKey,
+        signers: &SignersContainer,
+        build_sat: BuildSatisfaction,
+        secp: &SecpCtx,
+    ) -> Policy;
+
+    fn find_signature(psbt: &Psbt, key: &DescriptorPublicKey, secp: &SecpCtx) -> bool;
+}
+
+impl<T: ScriptContext + 'static> SigExt for T {
+    fn make_signature(
+        key: &DescriptorPublicKey,
+        signers: &SignersContainer,
+        build_sat: BuildSatisfaction,
+        secp: &SecpCtx,
+    ) -> Policy {
+        if T::as_enum().is_taproot() {
+            make_generic_signature(
+                key,
+                signers,
+                build_sat,
+                secp,
+                || SatisfiableItem::SchnorrSignature(PkOrF::from_key(key, secp)),
+                |psbt| Self::find_signature(psbt, key, secp),
+            )
+        } else {
+            make_generic_signature(
+                key,
+                signers,
+                build_sat,
+                secp,
+                || SatisfiableItem::EcdsaSignature(PkOrF::from_key(key, secp)),
+                |psbt| Self::find_signature(psbt, key, secp),
+            )
+        }
+    }
+
+    fn find_signature(psbt: &Psbt, key: &DescriptorPublicKey, secp: &SecpCtx) -> bool {
+        if T::as_enum().is_taproot() {
+            generic_sig_in_psbt(
+                psbt,
+                key,
+                secp,
+                |input, pk| {
+                    let pk = match pk {
+                        SinglePubKey::XOnly(pk) => pk,
+                        _ => return false,
+                    };
+
+                    if input.tap_internal_key == Some(*pk) && input.tap_key_sig.is_some() {
+                        true
+                    } else {
+                        input.tap_script_sigs.keys().any(|(sk, _)| sk == pk)
+                    }
+                },
+                |input, fing| {
+                    input
+                        .tap_key_origins
+                        .iter()
+                        .find(|(_, (_, (f, _)))| f == &fing)
+                        .map(|(pk, _)| SinglePubKey::XOnly(*pk))
+                },
+            )
+        } else {
+            generic_sig_in_psbt(
+                psbt,
+                key,
+                secp,
+                |input, pk| match pk {
+                    SinglePubKey::FullKey(pk) => input.partial_sigs.contains_key(pk),
+                    _ => false,
+                },
+                |input, fing| {
+                    input
+                        .bip32_derivation
+                        .iter()
+                        .find(|(_, (f, _))| f == &fing)
+                        .map(|(pk, _)| SinglePubKey::FullKey(PublicKey::new(*pk)))
+                },
+            )
+        }
+    }
+}
+
+impl<Ctx: ScriptContext + 'static> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
+    fn extract_policy(
+        &self,
+        signers: &SignersContainer,
+        build_sat: BuildSatisfaction,
+        secp: &SecpCtx,
+    ) -> Result<Option<Policy>, Error> {
+        Ok(match &self.node {
+            // Leaves
+            Terminal::True | Terminal::False => None,
+            Terminal::PkK(pubkey) => Some(Ctx::make_signature(pubkey, signers, build_sat, secp)),
+            Terminal::PkH(pubkey_hash) => {
+                Some(Ctx::make_signature(pubkey_hash, signers, build_sat, secp))
+            }
+            Terminal::After(value) => {
+                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock {
+                    value: (*value).into(),
+                }
+                .into();
+                policy.contribution = Satisfaction::Complete {
+                    condition: Condition {
+                        timelock: Some((*value).into()),
+                        csv: None,
+                    },
+                };
+                if let BuildSatisfaction::PsbtTimelocks {
+                    current_height,
+                    psbt,
+                    ..
+                } = build_sat
+                {
+                    let after = After::new(Some(current_height), false);
+                    let after_sat =
+                        Satisfier::<bitcoin::PublicKey>::check_after(&after, (*value).into());
+                    let inputs_sat = psbt_inputs_sat(psbt).all(|sat| {
+                        Satisfier::<bitcoin::PublicKey>::check_after(&sat, (*value).into())
+                    });
+                    if after_sat && inputs_sat {
+                        policy.satisfaction = policy.contribution.clone();
+                    }
+                }
+
+                Some(policy)
+            }
+            Terminal::Older(value) => {
+                let mut policy: Policy = SatisfiableItem::RelativeTimelock { value: *value }.into();
+                policy.contribution = Satisfaction::Complete {
+                    condition: Condition {
+                        timelock: None,
+                        csv: Some(*value),
+                    },
+                };
+                if let BuildSatisfaction::PsbtTimelocks {
+                    current_height,
+                    input_max_height,
+                    psbt,
+                } = build_sat
+                {
+                    let older = Older::new(Some(current_height), Some(input_max_height), false);
+                    let older_sat = Satisfier::<bitcoin::PublicKey>::check_older(&older, *value);
+                    let inputs_sat = psbt_inputs_sat(psbt)
+                        .all(|sat| Satisfier::<bitcoin::PublicKey>::check_older(&sat, *value));
+                    if older_sat && inputs_sat {
+                        policy.satisfaction = policy.contribution.clone();
+                    }
+                }
+
+                Some(policy)
+            }
+            Terminal::Sha256(hash) => Some(SatisfiableItem::Sha256Preimage { hash: *hash }.into()),
+            Terminal::Hash256(hash) => {
+                Some(SatisfiableItem::Hash256Preimage { hash: *hash }.into())
+            }
+            Terminal::Ripemd160(hash) => {
+                Some(SatisfiableItem::Ripemd160Preimage { hash: *hash }.into())
+            }
+            Terminal::Hash160(hash) => {
+                Some(SatisfiableItem::Hash160Preimage { hash: *hash }.into())
+            }
+            Terminal::Multi(k, pks) | Terminal::MultiA(k, pks) => {
+                Policy::make_multisig::<Ctx>(pks, signers, build_sat, *k, false, secp)?
+            }
+            // Identities
+            Terminal::Alt(inner)
+            | Terminal::Swap(inner)
+            | Terminal::Check(inner)
+            | Terminal::DupIf(inner)
+            | Terminal::Verify(inner)
+            | Terminal::NonZero(inner)
+            | Terminal::ZeroNotEqual(inner) => inner.extract_policy(signers, build_sat, secp)?,
+            // Complex policies
+            Terminal::AndV(a, b) | Terminal::AndB(a, b) => Policy::make_and(
+                a.extract_policy(signers, build_sat, secp)?,
+                b.extract_policy(signers, build_sat, secp)?,
+            )?,
+            Terminal::AndOr(x, y, z) => Policy::make_or(
+                Policy::make_and(
+                    x.extract_policy(signers, build_sat, secp)?,
+                    y.extract_policy(signers, build_sat, secp)?,
+                )?,
+                z.extract_policy(signers, build_sat, secp)?,
+            )?,
+            Terminal::OrB(a, b)
+            | Terminal::OrD(a, b)
+            | Terminal::OrC(a, b)
+            | Terminal::OrI(a, b) => Policy::make_or(
+                a.extract_policy(signers, build_sat, secp)?,
+                b.extract_policy(signers, build_sat, secp)?,
+            )?,
+            Terminal::Thresh(k, nodes) => {
+                let mut threshold = *k;
+                let mapped: Vec<_> = nodes
+                    .iter()
+                    .map(|n| n.extract_policy(signers, build_sat, secp))
+                    .collect::<Result<Vec<_>, _>>()?
+                    .into_iter()
+                    .flatten()
+                    .collect();
+
+                if mapped.len() < nodes.len() {
+                    threshold = match threshold.checked_sub(nodes.len() - mapped.len()) {
+                        None => return Ok(None),
+                        Some(x) => x,
+                    };
+                }
+
+                Policy::make_thresh(mapped, threshold)?
+            }
+
+            // Unsupported
+            Terminal::RawPkH(_) => None,
+        })
+    }
+}
+
+fn psbt_inputs_sat(psbt: &Psbt) -> impl Iterator<Item = PsbtInputSatisfier> {
+    (0..psbt.inputs.len()).map(move |i| PsbtInputSatisfier::new(psbt, i))
+}
+
+/// Options to build the satisfaction field in the policy
+#[derive(Debug, Clone, Copy)]
+pub enum BuildSatisfaction<'a> {
+    /// Don't generate `satisfaction` field
+    None,
+    /// Analyze the given PSBT to check for existing signatures
+    Psbt(&'a Psbt),
+    /// Like `Psbt` variant and also check for expired timelocks
+    PsbtTimelocks {
+        /// Given PSBT
+        psbt: &'a Psbt,
+        /// Current blockchain height
+        current_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
+        input_max_height: u32,
+    },
+}
+impl<'a> BuildSatisfaction<'a> {
+    fn psbt(&self) -> Option<&'a Psbt> {
+        match self {
+            BuildSatisfaction::None => None,
+            BuildSatisfaction::Psbt(psbt) => Some(psbt),
+            BuildSatisfaction::PsbtTimelocks { psbt, .. } => Some(psbt),
+        }
+    }
+}
+
+impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
+    fn extract_policy(
+        &self,
+        signers: &SignersContainer,
+        build_sat: BuildSatisfaction,
+        secp: &SecpCtx,
+    ) -> Result<Option<Policy>, Error> {
+        fn make_sortedmulti<Ctx: ScriptContext + 'static>(
+            keys: &SortedMultiVec<DescriptorPublicKey, Ctx>,
+            signers: &SignersContainer,
+            build_sat: BuildSatisfaction,
+            secp: &SecpCtx,
+        ) -> Result<Option<Policy>, Error> {
+            Ok(Policy::make_multisig::<Ctx>(
+                keys.pks.as_ref(),
+                signers,
+                build_sat,
+                keys.k,
+                true,
+                secp,
+            )?)
+        }
+
+        match self {
+            Descriptor::Pkh(pk) => Ok(Some(miniscript::Legacy::make_signature(
+                pk.as_inner(),
+                signers,
+                build_sat,
+                secp,
+            ))),
+            Descriptor::Wpkh(pk) => Ok(Some(miniscript::Segwitv0::make_signature(
+                pk.as_inner(),
+                signers,
+                build_sat,
+                secp,
+            ))),
+            Descriptor::Sh(sh) => match sh.as_inner() {
+                ShInner::Wpkh(pk) => Ok(Some(miniscript::Segwitv0::make_signature(
+                    pk.as_inner(),
+                    signers,
+                    build_sat,
+                    secp,
+                ))),
+                ShInner::Ms(ms) => Ok(ms.extract_policy(signers, build_sat, secp)?),
+                ShInner::SortedMulti(ref keys) => make_sortedmulti(keys, signers, build_sat, secp),
+                ShInner::Wsh(wsh) => match wsh.as_inner() {
+                    WshInner::Ms(ms) => Ok(ms.extract_policy(signers, build_sat, secp)?),
+                    WshInner::SortedMulti(ref keys) => {
+                        make_sortedmulti(keys, signers, build_sat, secp)
+                    }
+                },
+            },
+            Descriptor::Wsh(wsh) => match wsh.as_inner() {
+                WshInner::Ms(ms) => Ok(ms.extract_policy(signers, build_sat, secp)?),
+                WshInner::SortedMulti(ref keys) => make_sortedmulti(keys, signers, build_sat, secp),
+            },
+            Descriptor::Bare(ms) => Ok(ms.as_inner().extract_policy(signers, build_sat, secp)?),
+            Descriptor::Tr(tr) => {
+                // If there's no tap tree, treat this as a single sig, otherwise build a `Thresh`
+                // node with threshold = 1 and the key spend signature plus all the tree leaves
+                let key_spend_sig =
+                    miniscript::Tap::make_signature(tr.internal_key(), signers, build_sat, secp);
+
+                if tr.tap_tree().is_none() {
+                    Ok(Some(key_spend_sig))
+                } else {
+                    let mut items = vec![key_spend_sig];
+                    items.append(
+                        &mut tr
+                            .iter_scripts()
+                            .filter_map(|(_, ms)| {
+                                ms.extract_policy(signers, build_sat, secp).transpose()
+                            })
+                            .collect::<Result<Vec<_>, _>>()?,
+                    );
+
+                    Ok(Policy::make_thresh(items, 1)?)
+                }
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::descriptor;
+    use crate::descriptor::{ExtractPolicy, IntoWalletDescriptor};
+
+    use super::*;
+    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::bip32;
+    use bitcoin::secp256k1::Secp256k1;
+    use bitcoin::Network;
+    use core::str::FromStr;
+
+    const TPRV0_STR:&str = "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf";
+    const TPRV1_STR:&str = "tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N";
+
+    const PATH: &str = "m/44'/1'/0'/0";
+
+    fn setup_keys<Ctx: ScriptContext>(
+        tprv: &str,
+        path: &str,
+        secp: &SecpCtx,
+    ) -> (DescriptorKey<Ctx>, DescriptorKey<Ctx>, Fingerprint) {
+        let path = bip32::DerivationPath::from_str(path).unwrap();
+        let tprv = bip32::Xpriv::from_str(tprv).unwrap();
+        let tpub = bip32::Xpub::from_priv(secp, &tprv);
+        let fingerprint = tprv.fingerprint(secp);
+        let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap();
+        let pubkey = (tpub, path).into_descriptor_key().unwrap();
+
+        (prvkey, pubkey, fingerprint)
+    }
+
+    // test ExtractPolicy trait for simple descriptors; wpkh(), sh(multi())
+
+    #[test]
+    fn test_extract_policy_for_wpkh() {
+        let secp = Secp256k1::new();
+
+        let (prvkey, pubkey, fingerprint) = setup_keys(TPRV0_STR, PATH, &secp);
+        let desc = descriptor!(wpkh(pubkey)).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint);
+        assert_matches!(&policy.contribution, Satisfaction::None);
+
+        let desc = descriptor!(wpkh(prvkey)).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint);
+        assert_matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv.is_none() && condition.timelock.is_none());
+    }
+
+    // 2 pub keys descriptor, required 2 prv keys
+    #[test]
+    fn test_extract_policy_for_sh_multi_partial_0of2() {
+        let secp = Secp256k1::new();
+        let (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
+        let (_prvkey1, pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
+        let desc = descriptor!(sh(multi(2, pubkey0, pubkey1))).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
+            && keys[0] == PkOrF::Fingerprint(fingerprint0)
+            && keys[1] == PkOrF::Fingerprint(fingerprint1)
+        );
+        // TODO should this be "Satisfaction::None" since we have no prv keys?
+        // TODO should items and conditions not be empty?
+        assert_matches!(&policy.contribution, Satisfaction::Partial { n, m, items, conditions, ..} if n == &2usize
+            && m == &2usize
+            && items.is_empty()
+            && conditions.is_empty()
+        );
+    }
+
+    // 1 prv and 1 pub key descriptor, required 2 prv keys
+    #[test]
+    fn test_extract_policy_for_sh_multi_partial_1of2() {
+        let secp = Secp256k1::new();
+        let (prvkey0, _pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
+        let (_prvkey1, pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
+        let desc = descriptor!(sh(multi(2, prvkey0, pubkey1))).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+        assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &2usize
+            && keys[0] == PkOrF::Fingerprint(fingerprint0)
+            && keys[1] == PkOrF::Fingerprint(fingerprint1)
+        );
+
+        assert_matches!(&policy.contribution, Satisfaction::Partial { n, m, items, conditions, ..} if n == &2usize
+             && m == &2usize
+             && items.len() == 1
+             && conditions.contains_key(&0)
+        );
+    }
+
+    // 1 prv and 1 pub key descriptor, required 1 prv keys
+    #[test]
+    #[ignore] // see https://github.com/bitcoindevkit/bdk/issues/225
+    fn test_extract_policy_for_sh_multi_complete_1of2() {
+        let secp = Secp256k1::new();
+
+        let (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
+        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
+        let desc = descriptor!(sh(multi(1, pubkey0, prvkey1))).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
+            && keys[0] == PkOrF::Fingerprint(fingerprint0)
+            && keys[1] == PkOrF::Fingerprint(fingerprint1)
+        );
+        assert_matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2
+             && m == &1
+             && items.len() == 2
+             && conditions.contains_key(&vec![0])
+             && conditions.contains_key(&vec![1])
+        );
+    }
+
+    // 2 prv keys descriptor, required 2 prv keys
+    #[test]
+    fn test_extract_policy_for_sh_multi_complete_2of2() {
+        let secp = Secp256k1::new();
+
+        let (prvkey0, _pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
+        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
+        let desc = descriptor!(sh(multi(2, prvkey0, prvkey1))).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
+            && keys[0] == PkOrF::Fingerprint(fingerprint0)
+            && keys[1] == PkOrF::Fingerprint(fingerprint1)
+        );
+
+        assert_matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &2
+             && m == &2
+             && items.len() == 2
+             && conditions.contains_key(&vec![0,1])
+        );
+    }
+
+    // test ExtractPolicy trait with extended and single keys
+
+    #[test]
+    fn test_extract_policy_for_single_wpkh() {
+        let secp = Secp256k1::new();
+
+        let (prvkey, pubkey, fingerprint) = setup_keys(TPRV0_STR, PATH, &secp);
+        let desc = descriptor!(wpkh(pubkey)).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(&policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == &fingerprint);
+        assert_matches!(&policy.contribution, Satisfaction::None);
+
+        let desc = descriptor!(wpkh(prvkey)).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(policy.item, EcdsaSignature(PkOrF::Fingerprint(f)) if f == fingerprint);
+        assert_matches!(policy.contribution, Satisfaction::Complete {condition} if condition.csv.is_none() && condition.timelock.is_none());
+    }
+
+    // single key, 1 prv and 1 pub key descriptor, required 1 prv keys
+    #[test]
+    #[ignore] // see https://github.com/bitcoindevkit/bdk/issues/225
+    fn test_extract_policy_for_single_wsh_multi_complete_1of2() {
+        let secp = Secp256k1::new();
+
+        let (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
+        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
+        let desc = descriptor!(sh(multi(1, pubkey0, prvkey1))).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(policy.item, Multisig { keys, threshold } if threshold == 1
+            && keys[0] == PkOrF::Fingerprint(fingerprint0)
+            && keys[1] == PkOrF::Fingerprint(fingerprint1)
+        );
+        assert_matches!(policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == 2
+             && m == 1
+             && items.len() == 2
+             && conditions.contains_key(&vec![0])
+             && conditions.contains_key(&vec![1])
+        );
+    }
+
+    // test ExtractPolicy trait with descriptors containing timelocks in a thresh()
+
+    #[test]
+    #[ignore] // see https://github.com/bitcoindevkit/bdk/issues/225
+    fn test_extract_policy_for_wsh_multi_timelock() {
+        let secp = Secp256k1::new();
+
+        let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
+        let (_prvkey1, pubkey1, _fingerprint1) = setup_keys(TPRV1_STR, PATH, &secp);
+        let sequence = 50;
+        #[rustfmt::skip]
+        let desc = descriptor!(wsh(thresh(
+            2,
+            pk(prvkey0),
+            s:pk(pubkey1),
+            s:d:v:older(sequence)
+        )))
+        .unwrap();
+
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(&policy.item, Thresh { items, threshold } if items.len() == 3 && threshold == &2);
+
+        assert_matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions, .. } if n == &3
+             && m == &2
+             && items.len() == 3
+             && conditions.get(&vec![0,1]).unwrap().iter().next().unwrap().csv.is_none()
+             && conditions.get(&vec![0,2]).unwrap().iter().next().unwrap().csv == Some(Sequence(sequence))
+             && conditions.get(&vec![1,2]).unwrap().iter().next().unwrap().csv == Some(Sequence(sequence))
+        );
+    }
+
+    // - mixed timelocks should fail
+
+    #[test]
+    #[ignore]
+    fn test_extract_policy_for_wsh_mixed_timelocks() {
+        let secp = Secp256k1::new();
+        let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
+        let locktime_threshold = 500000000; // if less than this means block number, else block time in seconds
+        let locktime_blocks = 100;
+        let locktime_seconds = locktime_blocks + locktime_threshold;
+        let desc = descriptor!(sh(and_v(
+            v: pk(prvkey0),
+            and_v(v: after(locktime_seconds), after(locktime_blocks))
+        )))
+        .unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        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?
+    }
+
+    // - multiple timelocks of the same type should be correctly merged together
+    #[test]
+    #[ignore]
+    fn test_extract_policy_for_multiple_same_timelocks() {
+        let secp = Secp256k1::new();
+        let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR, PATH, &secp);
+        let locktime_blocks0 = 100;
+        let locktime_blocks1 = 200;
+        let desc = descriptor!(sh(and_v(
+            v: pk(prvkey0),
+            and_v(v: after(locktime_blocks0), after(locktime_blocks1))
+        )))
+        .unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        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?
+        let (prvkey1, _pubkey1, _fingerprint1) = setup_keys(TPRV0_STR, PATH, &secp);
+        let locktime_seconds0 = 500000100;
+        let locktime_seconds1 = 500000200;
+        let desc = descriptor!(sh(and_v(
+            v: pk(prvkey1),
+            and_v(v: after(locktime_seconds0), after(locktime_seconds1))
+        )))
+        .unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+        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?
+    }
+
+    #[test]
+    fn test_get_condition_multisig() {
+        let secp = Secp256k1::new();
+
+        let (_, pk0, _) = setup_keys(TPRV0_STR, PATH, &secp);
+        let (_, pk1, _) = setup_keys(TPRV1_STR, PATH, &secp);
+
+        let desc = descriptor!(wsh(multi(1, pk0, pk1))).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        // no args, choose the default
+        let no_args = policy.get_condition(&vec![].into_iter().collect());
+        assert_eq!(no_args, Ok(Condition::default()));
+
+        // enough args
+        let eq_thresh =
+            policy.get_condition(&vec![(policy.id.clone(), vec![0])].into_iter().collect());
+        assert_eq!(eq_thresh, Ok(Condition::default()));
+
+        // more args, it doesn't really change anything
+        let gt_thresh =
+            policy.get_condition(&vec![(policy.id.clone(), vec![0, 1])].into_iter().collect());
+        assert_eq!(gt_thresh, Ok(Condition::default()));
+
+        // not enough args, error
+        let lt_thresh =
+            policy.get_condition(&vec![(policy.id.clone(), vec![])].into_iter().collect());
+        assert_eq!(
+            lt_thresh,
+            Err(PolicyError::NotEnoughItemsSelected(policy.id.clone()))
+        );
+
+        // index out of range
+        let out_of_range =
+            policy.get_condition(&vec![(policy.id.clone(), vec![5])].into_iter().collect());
+        assert_eq!(out_of_range, Err(PolicyError::IndexOutOfRange(5)));
+    }
+
+    const ALICE_TPRV_STR:&str = "tprv8ZgxMBicQKsPf6T5X327efHnvJDr45Xnb8W4JifNWtEoqXu9MRYS4v1oYe6DFcMVETxy5w3bqpubYRqvcVTqovG1LifFcVUuJcbwJwrhYzP";
+    const BOB_TPRV_STR:&str = "tprv8ZgxMBicQKsPeinZ155cJAn117KYhbaN6MV3WeG6sWhxWzcvX1eg1awd4C9GpUN1ncLEM2rzEvunAg3GizdZD4QPPCkisTz99tXXB4wZArp";
+    const CAROL_TPRV_STR:&str = "tprv8ZgxMBicQKsPdC3CicFifuLCEyVVdXVUNYorxUWj3iGZ6nimnLAYAY9SYB7ib8rKzRxrCKFcEytCt6szwd2GHnGPRCBLAEAoSVDefSNk4Bt";
+    const ALICE_BOB_PATH: &str = "m/0'";
+
+    #[test]
+    fn test_extract_satisfaction() {
+        const ALICE_SIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAZb0njwT2wRS3AumaaP3yb7T4MxOePpSWih4Nq+jWChMAQAAAAD/////Af4lAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASuJJgAAAAAAACIAIERw5kTLo9DUH9QDJSClHQwPpC7VGJ+ZMDpa8U+2fzcYIgIDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42ZstHMEQCIBj0jLjUeVYXNQ6cqB+gbtvuKMjV54wSgWlm1cfcgpHVAiBa3DtC9l/1Mt4IDCvR7mmwQd3eAP/m5++81euhJNSrgQEBBUdSIQN4C2NhCT9V+7h1vb7ryHIwqNzfz6RaXmw/lAfwvjZmyyEC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhSriIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAAA";
+        const BOB_SIGNED_PSBT: &str =   "cHNidP8BAFMBAAAAAZb0njwT2wRS3AumaaP3yb7T4MxOePpSWih4Nq+jWChMAQAAAAD/////Af4lAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASuJJgAAAAAAACIAIERw5kTLo9DUH9QDJSClHQwPpC7VGJ+ZMDpa8U+2fzcYIgIC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhIMEUCIQD5zDtM5MwklurwJ5aW76RsO36Iqyu+6uMdVlhL6ws2GQIgesAiz4dbKS7UmhDsC/c1ezu0o6hp00UUtsCMfUZ4anYBAQVHUiEDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42ZsshAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIUq4iBgL4YT/L4um0jzGaJHqw5733wgbPJujHRB/Pj4FCXWeZiAwcLu4+AAAAgAAAAAAiBgN4C2NhCT9V+7h1vb7ryHIwqNzfz6RaXmw/lAfwvjZmywzJEXwuAAAAgAAAAAAAAA==";
+        const ALICE_BOB_SIGNED_PSBT: &str =   "cHNidP8BAFMBAAAAAZb0njwT2wRS3AumaaP3yb7T4MxOePpSWih4Nq+jWChMAQAAAAD/////Af4lAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASuJJgAAAAAAACIAIERw5kTLo9DUH9QDJSClHQwPpC7VGJ+ZMDpa8U+2fzcYIgIC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhIMEUCIQD5zDtM5MwklurwJ5aW76RsO36Iqyu+6uMdVlhL6ws2GQIgesAiz4dbKS7UmhDsC/c1ezu0o6hp00UUtsCMfUZ4anYBIgIDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42ZstHMEQCIBj0jLjUeVYXNQ6cqB+gbtvuKMjV54wSgWlm1cfcgpHVAiBa3DtC9l/1Mt4IDCvR7mmwQd3eAP/m5++81euhJNSrgQEBBUdSIQN4C2NhCT9V+7h1vb7ryHIwqNzfz6RaXmw/lAfwvjZmyyEC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhSriIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAEHAAEI2wQARzBEAiAY9Iy41HlWFzUOnKgfoG7b7ijI1eeMEoFpZtXH3IKR1QIgWtw7QvZf9TLeCAwr0e5psEHd3gD/5ufvvNXroSTUq4EBSDBFAiEA+cw7TOTMJJbq8CeWlu+kbDt+iKsrvurjHVZYS+sLNhkCIHrAIs+HWyku1JoQ7Av3NXs7tKOoadNFFLbAjH1GeGp2AUdSIQN4C2NhCT9V+7h1vb7ryHIwqNzfz6RaXmw/lAfwvjZmyyEC+GE/y+LptI8xmiR6sOe998IGzybox0Qfz4+BQl1nmYhSrgAA";
+
+        let secp = Secp256k1::new();
+
+        let (prvkey_alice, _, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
+        let (prvkey_bob, _, _) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
+
+        let desc = descriptor!(wsh(multi(2, prvkey_alice, prvkey_bob))).unwrap();
+
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+
+        let addr = wallet_desc
+            .at_derivation_index(0)
+            .unwrap()
+            .address(Network::Testnet)
+            .unwrap();
+        assert_eq!(
+            "tb1qg3cwv3xt50gdg875qvjjpfgaps86gtk4rz0ejvp6ttc5ldnlxuvqlcn0xk",
+            addr.to_string()
+        );
+
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+
+        let psbt = Psbt::from_str(ALICE_SIGNED_PSBT).unwrap();
+
+        let policy_alice_psbt = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::Psbt(&psbt), &secp)
+            .unwrap()
+            .unwrap();
+        //println!("{}", serde_json::to_string(&policy_alice_psbt).unwrap());
+
+        assert_matches!(&policy_alice_psbt.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &2
+             && m == &2
+             && items == &vec![0]
+        );
+
+        let psbt = Psbt::from_str(BOB_SIGNED_PSBT).unwrap();
+        let policy_bob_psbt = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::Psbt(&psbt), &secp)
+            .unwrap()
+            .unwrap();
+        //println!("{}", serde_json::to_string(&policy_bob_psbt).unwrap());
+
+        assert_matches!(&policy_bob_psbt.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &2
+             && m == &2
+             && items == &vec![1]
+        );
+
+        let psbt = Psbt::from_str(ALICE_BOB_SIGNED_PSBT).unwrap();
+        let policy_alice_bob_psbt = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::Psbt(&psbt), &secp)
+            .unwrap()
+            .unwrap();
+        assert_matches!(&policy_alice_bob_psbt.satisfaction, Satisfaction::PartialComplete { n, m, items, .. } if n == &2
+             && m == &2
+             && items == &vec![0, 1]
+        );
+    }
+
+    #[test]
+    fn test_extract_satisfaction_timelock() {
+        //const PSBT_POLICY_CONSIDER_TIMELOCK_NOT_EXPIRED: &str = "cHNidP8BAFMBAAAAAdld52uJFGT7Yde0YZdSVh2vL020Zm2exadH5R4GSNScAAAAAAD/////ATrcAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASvI3AAAAAAAACIAILhzvvcBzw/Zfnc9ispRK0PCahxn1F6RHXTZAmw5tqNPAQVSdmNSsmlofCEDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42Zsusk3whAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIrJNShyIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAAA";
+        const PSBT_POLICY_CONSIDER_TIMELOCK_EXPIRED:     &str = "cHNidP8BAFMCAAAAAdld52uJFGT7Yde0YZdSVh2vL020Zm2exadH5R4GSNScAAAAAAACAAAAATrcAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASvI3AAAAAAAACIAILhzvvcBzw/Zfnc9ispRK0PCahxn1F6RHXTZAmw5tqNPAQVSdmNSsmlofCEDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42Zsusk3whAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIrJNShyIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAAA";
+        const PSBT_POLICY_CONSIDER_TIMELOCK_EXPIRED_SIGNED: &str ="cHNidP8BAFMCAAAAAdld52uJFGT7Yde0YZdSVh2vL020Zm2exadH5R4GSNScAAAAAAACAAAAATrcAAAAAAAAF6kUXv2Fn+YemPP4PUpNR1ZbU16/eRCHAAAAAAABASvI3AAAAAAAACIAILhzvvcBzw/Zfnc9ispRK0PCahxn1F6RHXTZAmw5tqNPIgIDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42ZstIMEUCIQCtZxNm6H3Ux3pnc64DSpgohMdBj+57xhFHcURYt2BpPAIgG3OnI7bcj/3GtWX1HHyYGSI7QGa/zq5YnsmK1Cw29NABAQVSdmNSsmlofCEDeAtjYQk/Vfu4db2+68hyMKjc38+kWl5sP5QH8L42Zsusk3whAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIrJNShyIGAvhhP8vi6bSPMZokerDnvffCBs8m6MdEH8+PgUJdZ5mIDBwu7j4AAACAAAAAACIGA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLDMkRfC4AAACAAAAAAAEHAAEIoAQASDBFAiEArWcTZuh91Md6Z3OuA0qYKITHQY/ue8YRR3FEWLdgaTwCIBtzpyO23I/9xrVl9Rx8mBkiO0Bmv86uWJ7JitQsNvTQAQEBUnZjUrJpaHwhA3gLY2EJP1X7uHW9vuvIcjCo3N/PpFpebD+UB/C+NmbLrJN8IQL4YT/L4um0jzGaJHqw5733wgbPJujHRB/Pj4FCXWeZiKyTUocAAA==";
+
+        let secp = Secp256k1::new();
+
+        let (prvkey_alice, _, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
+        let (prvkey_bob, _, _) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
+
+        let desc =
+            descriptor!(wsh(thresh(2,n:d:v:older(2),s:pk(prvkey_alice),s:pk(prvkey_bob)))).unwrap();
+
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+
+        let addr = wallet_desc
+            .at_derivation_index(0)
+            .unwrap()
+            .address(Network::Testnet)
+            .unwrap();
+        assert_eq!(
+            "tb1qsydsey4hexagwkvercqsmes6yet0ndkyt6uzcphtqnygjd8hmzmsfxrv58",
+            addr.to_string()
+        );
+
+        let psbt = Psbt::from_str(PSBT_POLICY_CONSIDER_TIMELOCK_EXPIRED).unwrap();
+
+        let build_sat = BuildSatisfaction::PsbtTimelocks {
+            psbt: &psbt,
+            current_height: 10,
+            input_max_height: 9,
+        };
+
+        let policy = wallet_desc
+            .extract_policy(&signers_container, build_sat, &secp)
+            .unwrap()
+            .unwrap();
+        assert_matches!(&policy.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &3
+             && m == &2
+             && items.is_empty()
+        );
+        //println!("{}", serde_json::to_string(&policy).unwrap());
+
+        let build_sat_expired = BuildSatisfaction::PsbtTimelocks {
+            psbt: &psbt,
+            current_height: 12,
+            input_max_height: 9,
+        };
+
+        let policy_expired = wallet_desc
+            .extract_policy(&signers_container, build_sat_expired, &secp)
+            .unwrap()
+            .unwrap();
+        assert_matches!(&policy_expired.satisfaction, Satisfaction::Partial { n, m, items, .. } if n == &3
+             && m == &2
+             && items == &vec![0]
+        );
+        //println!("{}", serde_json::to_string(&policy_expired).unwrap());
+
+        let psbt_signed = Psbt::from_str(PSBT_POLICY_CONSIDER_TIMELOCK_EXPIRED_SIGNED).unwrap();
+
+        let build_sat_expired_signed = BuildSatisfaction::PsbtTimelocks {
+            psbt: &psbt_signed,
+            current_height: 12,
+            input_max_height: 9,
+        };
+
+        let policy_expired_signed = wallet_desc
+            .extract_policy(&signers_container, build_sat_expired_signed, &secp)
+            .unwrap()
+            .unwrap();
+        assert_matches!(&policy_expired_signed.satisfaction, Satisfaction::PartialComplete { n, m, items, .. } if n == &3
+             && m == &2
+             && items == &vec![0, 1]
+        );
+        //println!("{}", serde_json::to_string(&policy_expired_signed).unwrap());
+    }
+
+    #[test]
+    fn test_extract_pkh() {
+        let secp = Secp256k1::new();
+
+        let (prvkey_alice, _, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
+        let (prvkey_bob, _, _) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
+        let (prvkey_carol, _, _) = setup_keys(CAROL_TPRV_STR, ALICE_BOB_PATH, &secp);
+
+        let desc = descriptor!(wsh(c: andor(
+            pk(prvkey_alice),
+            pk_k(prvkey_bob),
+            pk_h(prvkey_carol),
+        )))
+        .unwrap();
+
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+
+        let policy = wallet_desc.extract_policy(&signers_container, BuildSatisfaction::None, &secp);
+        assert!(policy.is_ok());
+    }
+
+    #[test]
+    fn test_extract_tr_key_spend() {
+        let secp = Secp256k1::new();
+
+        let (prvkey, _, fingerprint) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
+
+        let desc = descriptor!(tr(prvkey)).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap();
+        assert_eq!(
+            policy,
+            Some(Policy {
+                id: "48u0tz0n".to_string(),
+                item: SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(fingerprint)),
+                satisfaction: Satisfaction::None,
+                contribution: Satisfaction::Complete {
+                    condition: Condition::default()
+                }
+            })
+        );
+    }
+
+    #[test]
+    fn test_extract_tr_script_spend() {
+        let secp = Secp256k1::new();
+
+        let (alice_prv, _, alice_fing) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
+        let (_, bob_pub, bob_fing) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
+
+        let desc = descriptor!(tr(bob_pub, pk(alice_prv))).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+        let signers_container = Arc::new(SignersContainer::build(keymap, &wallet_desc, &secp));
+
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(policy.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2);
+        assert_matches!(policy.contribution, Satisfaction::PartialComplete { n: 2, m: 1, items, .. } if items == vec![1]);
+
+        let alice_sig = SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(alice_fing));
+        let bob_sig = SatisfiableItem::SchnorrSignature(PkOrF::Fingerprint(bob_fing));
+
+        let thresh_items = match policy.item {
+            SatisfiableItem::Thresh { items, .. } => items,
+            _ => unreachable!(),
+        };
+
+        assert_eq!(thresh_items[0].item, bob_sig);
+        assert_eq!(thresh_items[1].item, alice_sig);
+    }
+
+    #[test]
+    fn test_extract_tr_satisfaction_key_spend() {
+        const UNSIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAUKgMCqtGLSiGYhsTols2UJ/VQQgQi/SXO38uXs2SahdAQAAAAD/////ARyWmAAAAAAAF6kU4R3W8CnGzZcSsaovTYu0X8vHt3WHAAAAAAABASuAlpgAAAAAACJRIEiEBFjbZa1xdjLfFjrKzuC1F1LeRyI/gL6IuGKNmUuSIRYnkGTDxwXMHP32fkDFoGJY28trxbkkVgR2z7jZa2pOJA0AyRF8LgAAAIADAAAAARcgJ5Bkw8cFzBz99n5AxaBiWNvLa8W5JFYEds+42WtqTiQAAA==";
+        const SIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAUKgMCqtGLSiGYhsTols2UJ/VQQgQi/SXO38uXs2SahdAQAAAAD/////ARyWmAAAAAAAF6kU4R3W8CnGzZcSsaovTYu0X8vHt3WHAAAAAAABASuAlpgAAAAAACJRIEiEBFjbZa1xdjLfFjrKzuC1F1LeRyI/gL6IuGKNmUuSARNAIsRvARpRxuyQosVA7guRQT9vXr+S25W2tnP2xOGBsSgq7A4RL8yrbvwDmNlWw9R0Nc/6t+IsyCyy7dD/lbUGgyEWJ5Bkw8cFzBz99n5AxaBiWNvLa8W5JFYEds+42WtqTiQNAMkRfC4AAACAAwAAAAEXICeQZMPHBcwc/fZ+QMWgYljby2vFuSRWBHbPuNlrak4kAAA=";
+
+        let unsigned_psbt = Psbt::from_str(UNSIGNED_PSBT).unwrap();
+        let signed_psbt = Psbt::from_str(SIGNED_PSBT).unwrap();
+
+        let secp = Secp256k1::new();
+
+        let (_, pubkey, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
+
+        let desc = descriptor!(tr(pubkey)).unwrap();
+        let (wallet_desc, _) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+
+        let policy_unsigned = wallet_desc
+            .extract_policy(
+                &SignersContainer::default(),
+                BuildSatisfaction::Psbt(&unsigned_psbt),
+                &secp,
+            )
+            .unwrap()
+            .unwrap();
+        let policy_signed = wallet_desc
+            .extract_policy(
+                &SignersContainer::default(),
+                BuildSatisfaction::Psbt(&signed_psbt),
+                &secp,
+            )
+            .unwrap()
+            .unwrap();
+
+        assert_eq!(policy_unsigned.satisfaction, Satisfaction::None);
+        assert_eq!(
+            policy_signed.satisfaction,
+            Satisfaction::Complete {
+                condition: Default::default()
+            }
+        );
+    }
+
+    #[test]
+    fn test_extract_tr_satisfaction_script_spend() {
+        const UNSIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAWZalxaErOL7P3WPIUc8DsjgE68S+ww+uqiqEI2SAwlPAAAAAAD/////AQiWmAAAAAAAF6kU4R3W8CnGzZcSsaovTYu0X8vHt3WHAAAAAAABASuAlpgAAAAAACJRINa6bLPZwp3/CYWoxyI3mLYcSC5f9LInAMUng94nspa2IhXBgiPY+kcolS1Hp0niOK/+7VHz6F+nsz8JVxnzWzkgToYjIHhGyuexxtRVKevRx4YwWR/W0r7LPHt6oS6DLlzyuYQarMAhFnhGyuexxtRVKevRx4YwWR/W0r7LPHt6oS6DLlzyuYQaLQH2onWFc3UR6I9ZhuHVeJCi5LNAf4APVd7mHn4BhdViHRwu7j4AAACAAgAAACEWgiPY+kcolS1Hp0niOK/+7VHz6F+nsz8JVxnzWzkgToYNAMkRfC4AAACAAgAAAAEXIIIj2PpHKJUtR6dJ4jiv/u1R8+hfp7M/CVcZ81s5IE6GARgg9qJ1hXN1EeiPWYbh1XiQouSzQH+AD1Xe5h5+AYXVYh0AAA==";
+        const SIGNED_PSBT: &str = "cHNidP8BAFMBAAAAAWZalxaErOL7P3WPIUc8DsjgE68S+ww+uqiqEI2SAwlPAAAAAAD/////AQiWmAAAAAAAF6kU4R3W8CnGzZcSsaovTYu0X8vHt3WHAAAAAAABASuAlpgAAAAAACJRINa6bLPZwp3/CYWoxyI3mLYcSC5f9LInAMUng94nspa2AQcAAQhCAUALcP9w/+Ddly9DWdhHTnQ9uCDWLPZjR6vKbKePswW2Ee6W5KNfrklus/8z98n7BQ1U4vADHk0FbadeeL8rrbHlARNAC3D/cP/g3ZcvQ1nYR050Pbgg1iz2Y0erymynj7MFthHuluSjX65JbrP/M/fJ+wUNVOLwAx5NBW2nXni/K62x5UEUeEbK57HG1FUp69HHhjBZH9bSvss8e3qhLoMuXPK5hBr2onWFc3UR6I9ZhuHVeJCi5LNAf4APVd7mHn4BhdViHUAXNmWieJ80Fs+PMa2C186YOBPZbYG/ieEUkagMwzJ788SoCucNdp5wnxfpuJVygFhglDrXGzujFtC82PrMohwuIhXBgiPY+kcolS1Hp0niOK/+7VHz6F+nsz8JVxnzWzkgToYjIHhGyuexxtRVKevRx4YwWR/W0r7LPHt6oS6DLlzyuYQarMAhFnhGyuexxtRVKevRx4YwWR/W0r7LPHt6oS6DLlzyuYQaLQH2onWFc3UR6I9ZhuHVeJCi5LNAf4APVd7mHn4BhdViHRwu7j4AAACAAgAAACEWgiPY+kcolS1Hp0niOK/+7VHz6F+nsz8JVxnzWzkgToYNAMkRfC4AAACAAgAAAAEXIIIj2PpHKJUtR6dJ4jiv/u1R8+hfp7M/CVcZ81s5IE6GARgg9qJ1hXN1EeiPWYbh1XiQouSzQH+AD1Xe5h5+AYXVYh0AAA==";
+
+        let unsigned_psbt = Psbt::from_str(UNSIGNED_PSBT).unwrap();
+        let signed_psbt = Psbt::from_str(SIGNED_PSBT).unwrap();
+
+        let secp = Secp256k1::new();
+
+        let (_, alice_pub, _) = setup_keys(ALICE_TPRV_STR, ALICE_BOB_PATH, &secp);
+        let (_, bob_pub, _) = setup_keys(BOB_TPRV_STR, ALICE_BOB_PATH, &secp);
+
+        let desc = descriptor!(tr(bob_pub, pk(alice_pub))).unwrap();
+        let (wallet_desc, _) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+
+        let policy_unsigned = wallet_desc
+            .extract_policy(
+                &SignersContainer::default(),
+                BuildSatisfaction::Psbt(&unsigned_psbt),
+                &secp,
+            )
+            .unwrap()
+            .unwrap();
+        let policy_signed = wallet_desc
+            .extract_policy(
+                &SignersContainer::default(),
+                BuildSatisfaction::Psbt(&signed_psbt),
+                &secp,
+            )
+            .unwrap()
+            .unwrap();
+
+        assert_matches!(policy_unsigned.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2);
+        assert_matches!(policy_unsigned.satisfaction, Satisfaction::Partial { n: 2, m: 1, items, .. } if items.is_empty());
+
+        assert_matches!(policy_signed.item, SatisfiableItem::Thresh { ref items, threshold: 1 } if items.len() == 2);
+        assert_matches!(policy_signed.satisfaction, Satisfaction::PartialComplete { n: 2, m: 1, items, .. } if items == vec![0, 1]);
+
+        let satisfied_items = match policy_signed.item {
+            SatisfiableItem::Thresh { items, .. } => items,
+            _ => unreachable!(),
+        };
+
+        assert_eq!(
+            satisfied_items[0].satisfaction,
+            Satisfaction::Complete {
+                condition: Default::default()
+            }
+        );
+        assert_eq!(
+            satisfied_items[1].satisfaction,
+            Satisfaction::Complete {
+                condition: Default::default()
+            }
+        );
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/template.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/template.rs.html new file mode 100644 index 0000000000..f807cebf66 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/descriptor/template.rs.html @@ -0,0 +1,1973 @@ +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
+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
+
// 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.
+
+//! 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.
+
+use bitcoin::bip32;
+use bitcoin::Network;
+
+use miniscript::{Legacy, Segwitv0, Tap};
+
+use super::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap};
+use crate::descriptor::DescriptorError;
+use crate::keys::{DerivableKey, IntoDescriptorKey, ValidNetworks};
+use crate::wallet::utils::SecpCtx;
+use crate::{descriptor, KeychainKind};
+
+/// Type alias for the return type of [`DescriptorTemplate`], [`descriptor!`](crate::descriptor!) and others
+pub type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);
+
+/// Trait for descriptor templates that can be built into a full descriptor
+///
+/// Since [`IntoWalletDescriptor`] is implemented for any [`DescriptorTemplate`], they can also be
+/// passed directly to the [`Wallet`](crate::Wallet) constructor.
+///
+/// ## Example
+///
+/// ```
+/// use bdk_wallet::descriptor::error::Error as DescriptorError;
+/// use bdk_wallet::keys::{IntoDescriptorKey, KeyError};
+/// use bdk_wallet::miniscript::Legacy;
+/// use bdk_wallet::template::{DescriptorTemplate, DescriptorTemplateOut};
+/// use bitcoin::Network;
+///
+/// struct MyP2PKH<K: IntoDescriptorKey<Legacy>>(K);
+///
+/// impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
+///     fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+///         Ok(bdk_wallet::descriptor!(pkh(self.0))?)
+///     }
+/// }
+/// ```
+pub trait DescriptorTemplate {
+    /// Build the complete descriptor
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError>;
+}
+
+/// Turns a [`DescriptorTemplate`] into a valid wallet descriptor by calling its
+/// [`build`](DescriptorTemplate::build) method
+impl<T: DescriptorTemplate> IntoWalletDescriptor for T {
+    fn into_wallet_descriptor(
+        self,
+        secp: &SecpCtx,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
+        self.build(network)?.into_wallet_descriptor(secp, network)
+    }
+}
+
+/// P2PKH template. Expands to a descriptor `pkh(key)`
+///
+/// ## Example
+///
+/// ```
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::Wallet;
+/// # use bdk_wallet::KeychainKind;
+/// use bdk_wallet::template::P2Pkh;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let mut wallet = Wallet::new_no_persist(P2Pkh(key), None, Network::Testnet)?;
+///
+/// assert_eq!(
+///     wallet
+///         .next_unused_address(KeychainKind::External)?
+///         .to_string(),
+///     "mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"
+/// );
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+pub struct P2Pkh<K: IntoDescriptorKey<Legacy>>(pub K);
+
+impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for P2Pkh<K> {
+    fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        descriptor!(pkh(self.0))
+    }
+}
+
+/// P2WPKH-P2SH template. Expands to a descriptor `sh(wpkh(key))`
+///
+/// ## Example
+///
+/// ```
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::Wallet;
+/// # use bdk_wallet::KeychainKind;
+/// use bdk_wallet::template::P2Wpkh_P2Sh;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let mut wallet = Wallet::new_no_persist(P2Wpkh_P2Sh(key), None, Network::Testnet)?;
+///
+/// assert_eq!(
+///     wallet
+///         .next_unused_address(KeychainKind::External)?
+///         .to_string(),
+///     "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
+/// );
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+#[allow(non_camel_case_types)]
+pub struct P2Wpkh_P2Sh<K: IntoDescriptorKey<Segwitv0>>(pub K);
+
+impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh_P2Sh<K> {
+    fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        descriptor!(sh(wpkh(self.0)))
+    }
+}
+
+/// P2WPKH template. Expands to a descriptor `wpkh(key)`
+///
+/// ## Example
+///
+/// ```
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::{Wallet};
+/// # use bdk_wallet::KeychainKind;
+/// use bdk_wallet::template::P2Wpkh;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let mut wallet = Wallet::new_no_persist(P2Wpkh(key), None, Network::Testnet)?;
+///
+/// assert_eq!(
+///     wallet
+///         .next_unused_address(KeychainKind::External)?
+///         .to_string(),
+///     "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
+/// );
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+pub struct P2Wpkh<K: IntoDescriptorKey<Segwitv0>>(pub K);
+
+impl<K: IntoDescriptorKey<Segwitv0>> DescriptorTemplate for P2Wpkh<K> {
+    fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        descriptor!(wpkh(self.0))
+    }
+}
+
+/// P2TR template. Expands to a descriptor `tr(key)`
+///
+/// ## Example
+///
+/// ```
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::Wallet;
+/// # use bdk_wallet::KeychainKind;
+/// use bdk_wallet::template::P2TR;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let mut wallet = Wallet::new_no_persist(P2TR(key), None, Network::Testnet)?;
+///
+/// assert_eq!(
+///     wallet
+///         .next_unused_address(KeychainKind::External)?
+///         .to_string(),
+///     "tb1pvjf9t34fznr53u5tqhejz4nr69luzkhlvsdsdfq9pglutrpve2xq7hps46"
+/// );
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+pub struct P2TR<K: IntoDescriptorKey<Tap>>(pub K);
+
+impl<K: IntoDescriptorKey<Tap>> DescriptorTemplate for P2TR<K> {
+    fn build(self, _network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        descriptor!(tr(self.0))
+    }
+}
+
+/// 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 std::str::FromStr;
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::{Wallet,  KeychainKind};
+/// use bdk_wallet::template::Bip44;
+///
+/// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let mut wallet = Wallet::new_no_persist(
+///     Bip44(key.clone(), KeychainKind::External),
+///     Some(Bip44(key, KeychainKind::Internal)),
+///     Network::Testnet,
+/// )?;
+///
+/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
+
+impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44<K> {
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Pkh(legacy::make_bipxx_private(44, self.0, self.1, network)?).build(network)
+    }
+}
+
+/// 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
+/// for the key.
+///
+/// ## Example
+///
+/// ```
+/// # use std::str::FromStr;
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::{Wallet,  KeychainKind};
+/// use bdk_wallet::template::Bip44Public;
+///
+/// let key = bitcoin::bip32::Xpub::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
+/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
+/// let mut wallet = Wallet::new_no_persist(
+///     Bip44Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+/// )?;
+///
+/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
+
+impl<K: DerivableKey<Legacy>> DescriptorTemplate for Bip44Public<K> {
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Pkh(legacy::make_bipxx_public(
+            44, self.0, self.1, self.2, network,
+        )?)
+        .build(network)
+    }
+}
+
+/// 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 std::str::FromStr;
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::{Wallet,  KeychainKind};
+/// use bdk_wallet::template::Bip49;
+///
+/// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let mut wallet = Wallet::new_no_persist(
+///     Bip49(key.clone(), KeychainKind::External),
+///     Some(Bip49(key, KeychainKind::Internal)),
+///     Network::Testnet,
+/// )?;
+///
+/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
+
+impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49<K> {
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Wpkh_P2Sh(segwit_v0::make_bipxx_private(49, self.0, self.1, network)?).build(network)
+    }
+}
+
+/// 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
+/// for the key.
+///
+/// ## Example
+///
+/// ```
+/// # use std::str::FromStr;
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::{Wallet,  KeychainKind};
+/// use bdk_wallet::template::Bip49Public;
+///
+/// let key = bitcoin::bip32::Xpub::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
+/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
+/// let mut wallet = Wallet::new_no_persist(
+///     Bip49Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+/// )?;
+///
+/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
+
+impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip49Public<K> {
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Wpkh_P2Sh(segwit_v0::make_bipxx_public(
+            49, self.0, self.1, self.2, network,
+        )?)
+        .build(network)
+    }
+}
+
+/// 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 std::str::FromStr;
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::{Wallet,  KeychainKind};
+/// use bdk_wallet::template::Bip84;
+///
+/// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let mut wallet = Wallet::new_no_persist(
+///     Bip84(key.clone(), KeychainKind::External),
+///     Some(Bip84(key, KeychainKind::Internal)),
+///     Network::Testnet,
+/// )?;
+///
+/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
+
+impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84<K> {
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Wpkh(segwit_v0::make_bipxx_private(84, self.0, self.1, network)?).build(network)
+    }
+}
+
+/// 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
+/// for the key.
+///
+/// ## Example
+///
+/// ```
+/// # use std::str::FromStr;
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::{Wallet,  KeychainKind};
+/// use bdk_wallet::template::Bip84Public;
+///
+/// let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
+/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
+/// let mut wallet = Wallet::new_no_persist(
+///     Bip84Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+/// )?;
+///
+/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.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);
+
+impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for Bip84Public<K> {
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Wpkh(segwit_v0::make_bipxx_public(
+            84, self.0, self.1, self.2, network,
+        )?)
+        .build(network)
+    }
+}
+
+/// BIP86 template. Expands to `tr(key/86'/{0,1}'/0'/{0,1}/*)`
+///
+/// Since there are hardened derivation steps, this template requires a private derivable key (generally a `xprv`/`tprv`).
+///
+/// See [`Bip86Public`] for a template that can work with a `xpub`/`tpub`.
+///
+/// ## Example
+///
+/// ```
+/// # use std::str::FromStr;
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::{Wallet,  KeychainKind};
+/// use bdk_wallet::template::Bip86;
+///
+/// let key = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let mut wallet = Wallet::new_no_persist(
+///     Bip86(key.clone(), KeychainKind::External),
+///     Some(Bip86(key, KeychainKind::Internal)),
+///     Network::Testnet,
+/// )?;
+///
+/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.to_string(), "tb1p5unlj09djx8xsjwe97269kqtxqpwpu2epeskgqjfk4lnf69v4tnqpp35qu");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDCiHofpEs47kx358bPdJmTZHmCDqQ8qw32upCSxHrSEdeeBs2T5Mq6QMB2ukeMqhNBiyhosBvJErteVhfURPGXPv3qLJPw5MVpHUewsbP2m/0/*)#dkgvr5hm");
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+pub struct Bip86<K: DerivableKey<Tap>>(pub K, pub KeychainKind);
+
+impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86<K> {
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2TR(segwit_v1::make_bipxx_private(86, self.0, self.1, network)?).build(network)
+    }
+}
+
+/// BIP86 public template. Expands to `tr(key/{0,1}/*)`
+///
+/// This assumes that the key used has already been derived with `m/86'/0'/0'` for Mainnet or `m/86'/1'/0'` for Testnet.
+///
+/// This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
+///
+/// See [`Bip86`] for a template that does the full derivation, but requires private data
+/// for the key.
+///
+/// ## Example
+///
+/// ```
+/// # use std::str::FromStr;
+/// # use bdk_wallet::bitcoin::{PrivateKey, Network};
+/// # use bdk_wallet::{Wallet,  KeychainKind};
+/// use bdk_wallet::template::Bip86Public;
+///
+/// let key = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
+/// let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f")?;
+/// let mut wallet = Wallet::new_no_persist(
+///     Bip86Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(Bip86Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+/// )?;
+///
+/// assert_eq!(wallet.next_unused_address(KeychainKind::External)?.to_string(), "tb1pwjp9f2k5n0xq73ecuu0c5njvgqr3vkh7yaylmpqvsuuaafymh0msvcmh37");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External).unwrap().to_string(), "tr([c55b303f/86'/1'/0']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#2p65srku");
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+pub struct Bip86Public<K: DerivableKey<Tap>>(pub K, pub bip32::Fingerprint, pub KeychainKind);
+
+impl<K: DerivableKey<Tap>> DescriptorTemplate for Bip86Public<K> {
+    fn build(self, network: Network) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2TR(segwit_v1::make_bipxx_public(
+            86, self.0, self.1, self.2, network,
+        )?)
+        .build(network)
+    }
+}
+
+macro_rules! expand_make_bipxx {
+    ( $mod_name:ident, $ctx:ty ) => {
+        mod $mod_name {
+            use super::*;
+
+            pub(super) fn make_bipxx_private<K: DerivableKey<$ctx>>(
+                bip: u32,
+                key: K,
+                keychain: KeychainKind,
+                network: Network,
+            ) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
+                let mut derivation_path = alloc::vec::Vec::with_capacity(4);
+                derivation_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
+
+                match network {
+                    Network::Bitcoin => {
+                        derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
+                    }
+                    _ => {
+                        derivation_path.push(bip32::ChildNumber::from_hardened_idx(1)?);
+                    }
+                }
+                derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
+
+                match keychain {
+                    KeychainKind::External => {
+                        derivation_path.push(bip32::ChildNumber::from_normal_idx(0)?)
+                    }
+                    KeychainKind::Internal => {
+                        derivation_path.push(bip32::ChildNumber::from_normal_idx(1)?)
+                    }
+                };
+
+                let derivation_path: bip32::DerivationPath = derivation_path.into();
+
+                Ok((key, derivation_path))
+            }
+            pub(super) fn make_bipxx_public<K: DerivableKey<$ctx>>(
+                bip: u32,
+                key: K,
+                parent_fingerprint: bip32::Fingerprint,
+                keychain: KeychainKind,
+                network: Network,
+            ) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
+                let derivation_path: bip32::DerivationPath = match keychain {
+                    KeychainKind::External => vec![bip32::ChildNumber::from_normal_idx(0)?].into(),
+                    KeychainKind::Internal => vec![bip32::ChildNumber::from_normal_idx(1)?].into(),
+                };
+
+                let source_path = bip32::DerivationPath::from(vec![
+                    bip32::ChildNumber::from_hardened_idx(bip)?,
+                    match network {
+                        Network::Bitcoin => bip32::ChildNumber::from_hardened_idx(0)?,
+                        _ => bip32::ChildNumber::from_hardened_idx(1)?,
+                    },
+                    bip32::ChildNumber::from_hardened_idx(0)?,
+                ]);
+
+                Ok((key, (parent_fingerprint, source_path), derivation_path))
+            }
+        }
+    };
+}
+
+expand_make_bipxx!(legacy, Legacy);
+expand_make_bipxx!(segwit_v0, Segwitv0);
+expand_make_bipxx!(segwit_v1, Tap);
+
+#[cfg(test)]
+mod test {
+    // test existing descriptor templates, make sure they are expanded to the right descriptors
+
+    use alloc::{string::ToString, vec::Vec};
+    use core::str::FromStr;
+
+    use super::*;
+    use crate::descriptor::{DescriptorError, DescriptorMeta};
+    use crate::keys::ValidNetworks;
+    use assert_matches::assert_matches;
+    use miniscript::descriptor::{DescriptorPublicKey, KeyMap};
+    use miniscript::Descriptor;
+
+    // BIP44 `pkh(key/44'/{0,1}'/0'/{0,1}/*)`
+    #[test]
+    fn test_bip44_template_cointype() {
+        use bitcoin::bip32::ChildNumber::{self, Hardened};
+
+        let xprvkey = bitcoin::bip32::Xpriv::from_str("xprv9s21ZrQH143K2fpbqApQL69a4oKdGVnVN52R82Ft7d1pSqgKmajF62acJo3aMszZb6qQ22QsVECSFxvf9uyxFUvFYQMq3QbtwtRSMjLAhMf").unwrap();
+        assert_eq!(Network::Bitcoin, xprvkey.network);
+        let xdesc = Bip44(xprvkey, KeychainKind::Internal)
+            .build(Network::Bitcoin)
+            .unwrap();
+
+        if let ExtendedDescriptor::Pkh(pkh) = xdesc.0 {
+            let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().unwrap().into();
+            let purpose = path.first().unwrap();
+            assert_matches!(purpose, Hardened { index: 44 });
+            let coin_type = path.get(1).unwrap();
+            assert_matches!(coin_type, Hardened { index: 0 });
+        }
+
+        let tprvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        assert_eq!(Network::Testnet, tprvkey.network);
+        let tdesc = Bip44(tprvkey, KeychainKind::Internal)
+            .build(Network::Testnet)
+            .unwrap();
+
+        if let ExtendedDescriptor::Pkh(pkh) = tdesc.0 {
+            let path: Vec<ChildNumber> = pkh.into_inner().full_derivation_path().unwrap().into();
+            let purpose = path.first().unwrap();
+            assert_matches!(purpose, Hardened { index: 44 });
+            let coin_type = path.get(1).unwrap();
+            assert_matches!(coin_type, Hardened { index: 1 });
+        }
+    }
+
+    // verify template descriptor generates expected address(es)
+    fn check(
+        desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>,
+        is_witness: bool,
+        is_taproot: bool,
+        is_fixed: bool,
+        network: Network,
+        expected: &[&str],
+    ) {
+        let (desc, _key_map, _networks) = desc.unwrap();
+        assert_eq!(desc.is_witness(), is_witness);
+        assert_eq!(desc.is_taproot(), is_taproot);
+        assert_eq!(!desc.has_wildcard(), is_fixed);
+        for i in 0..expected.len() {
+            let index = i as u32;
+            let child_desc = if !desc.has_wildcard() {
+                desc.at_derivation_index(0).unwrap()
+            } else {
+                desc.at_derivation_index(index).unwrap()
+            };
+            let address = child_desc.address(network).unwrap();
+            assert_eq!(address.to_string(), *expected.get(i).unwrap());
+        }
+    }
+
+    // P2PKH
+    #[test]
+    fn test_p2ph_template() {
+        let prvkey =
+            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
+                .unwrap();
+        check(
+            P2Pkh(prvkey).build(Network::Bitcoin),
+            false,
+            false,
+            true,
+            Network::Regtest,
+            &["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2Pkh(pubkey).build(Network::Bitcoin),
+            false,
+            false,
+            true,
+            Network::Regtest,
+            &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
+        );
+    }
+
+    // P2WPKH-P2SH `sh(wpkh(key))`
+    #[test]
+    fn test_p2wphp2sh_template() {
+        let prvkey =
+            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
+                .unwrap();
+        check(
+            P2Wpkh_P2Sh(prvkey).build(Network::Bitcoin),
+            true,
+            false,
+            true,
+            Network::Regtest,
+            &["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2Wpkh_P2Sh(pubkey).build(Network::Bitcoin),
+            true,
+            false,
+            true,
+            Network::Regtest,
+            &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
+        );
+    }
+
+    // P2WPKH `wpkh(key)`
+    #[test]
+    fn test_p2wph_template() {
+        let prvkey =
+            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
+                .unwrap();
+        check(
+            P2Wpkh(prvkey).build(Network::Bitcoin),
+            true,
+            false,
+            true,
+            Network::Regtest,
+            &["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2Wpkh(pubkey).build(Network::Bitcoin),
+            true,
+            false,
+            true,
+            Network::Regtest,
+            &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
+        );
+    }
+
+    // P2TR `tr(key)`
+    #[test]
+    fn test_p2tr_template() {
+        let prvkey =
+            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
+                .unwrap();
+        check(
+            P2TR(prvkey).build(Network::Bitcoin),
+            false,
+            true,
+            true,
+            Network::Regtest,
+            &["bcrt1pvjf9t34fznr53u5tqhejz4nr69luzkhlvsdsdfq9pglutrpve2xqnwtkqq"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2TR(pubkey).build(Network::Bitcoin),
+            false,
+            true,
+            true,
+            Network::Regtest,
+            &["bcrt1pw74tdcrxlzn5r8z6ku2vztr86fgq0m245s72mjktf4afwzsf8ugs4evwdf"],
+        );
+    }
+
+    // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)`
+    #[test]
+    fn test_bip44_template() {
+        let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        check(
+            Bip44(prvkey, KeychainKind::External).build(Network::Bitcoin),
+            false,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "n453VtnjDHPyDt2fDstKSu7A3YCJoHZ5g5",
+                "mvfrrumXgTtwFPWDNUecBBgzuMXhYM7KRP",
+                "mzYvhRAuQqbdSKMVVzXNYyqihgNdRadAUQ",
+            ],
+        );
+        check(
+            Bip44(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
+            false,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "muHF98X9KxEzdKrnFAX85KeHv96eXopaip",
+                "n4hpyLJE5ub6B5Bymv4eqFxS5KjrewSmYR",
+                "mgvkdv1ffmsXd2B1sRKQ5dByK3SzpG42rA",
+            ],
+        );
+    }
+
+    // BIP44 public `pkh(key/{0,1}/*)`
+    #[test]
+    fn test_bip44_public_template() {
+        let pubkey = bitcoin::bip32::Xpub::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
+        let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap();
+        check(
+            Bip44Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
+            false,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "miNG7dJTzJqNbFS19svRdTCisC65dsubtR",
+                "n2UqaDbCjWSFJvpC84m3FjUk5UaeibCzYg",
+                "muCPpS6Ue7nkzeJMWDViw7Lkwr92Yc4K8g",
+            ],
+        );
+        check(
+            Bip44Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
+            false,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "moDr3vJ8wpt5nNxSK55MPq797nXJb2Ru9H",
+                "ms7A1Yt4uTezT2XkefW12AvLoko8WfNJMG",
+                "mhYiyat2rtEnV77cFfQsW32y1m2ceCGHPo",
+            ],
+        );
+    }
+
+    // BIP49 `sh(wpkh(key/49'/0'/0'/{0,1}/*))`
+    #[test]
+    fn test_bip49_template() {
+        let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        check(
+            Bip49(prvkey, KeychainKind::External).build(Network::Bitcoin),
+            true,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "2N9bCAJXGm168MjVwpkBdNt6ucka3PKVoUV",
+                "2NDckYkqrYyDMtttEav5hB3Bfw9EGAW5HtS",
+                "2NAFTVtksF9T4a97M7nyCjwUBD24QevZ5Z4",
+            ],
+        );
+        check(
+            Bip49(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
+            true,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "2NB3pA8PnzJLGV8YEKNDFpbViZv3Bm1K6CG",
+                "2NBiX2Wzxngb5rPiWpUiJQ2uLVB4HBjFD4p",
+                "2NA8ek4CdQ6aMkveYF6AYuEYNrftB47QGTn",
+            ],
+        );
+    }
+
+    // BIP49 public `sh(wpkh(key/{0,1}/*))`
+    #[test]
+    fn test_bip49_public_template() {
+        let pubkey = bitcoin::bip32::Xpub::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
+        let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap();
+        check(
+            Bip49Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
+            true,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt",
+                "2NCTQfJ1sZa3wQ3pPseYRHbaNEpC3AquEfX",
+                "2MveFxAuC8BYPzTybx7FxSzW8HSd8ATT4z7",
+            ],
+        );
+        check(
+            Bip49Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
+            true,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "2NF2vttKibwyxigxtx95Zw8K7JhDbo5zPVJ",
+                "2Mtmyd8taksxNVWCJ4wVvaiss7QPZGcAJuH",
+                "2NBs3CTVYPr1HCzjB4YFsnWCPCtNg8uMEfp",
+            ],
+        );
+    }
+
+    // BIP84 `wpkh(key/84'/0'/0'/{0,1}/*)`
+    #[test]
+    fn test_bip84_template() {
+        let prvkey = bitcoin::bip32::Xpriv::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        check(
+            Bip84(prvkey, KeychainKind::External).build(Network::Bitcoin),
+            true,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s",
+                "bcrt1qx0v6zgfwe50m4kqc58cqzcyem7ay2sfl3gvqhp",
+                "bcrt1q4h7fq9zhxst6e69p3n882nfj649l7w9g3zccfp",
+            ],
+        );
+        check(
+            Bip84(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
+            true,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa",
+                "bcrt1qqqasfhxpkkf7zrxqnkr2sfhn74dgsrc3e3ky45",
+                "bcrt1qpks7n0gq74hsgsz3phn5vuazjjq0f5eqhsgyce",
+            ],
+        );
+    }
+
+    // BIP84 public `wpkh(key/{0,1}/*)`
+    #[test]
+    fn test_bip84_public_template() {
+        let pubkey = bitcoin::bip32::Xpub::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
+        let fingerprint = bitcoin::bip32::Fingerprint::from_str("c55b303f").unwrap();
+        check(
+            Bip84Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
+            true,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "bcrt1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2prcdvd0h",
+                "bcrt1q3lncdlwq3lgcaaeyruynjnlccr0ve0kakh6ana",
+                "bcrt1qt9800y6xl3922jy3uyl0z33jh5wfpycyhcylr9",
+            ],
+        );
+        check(
+            Bip84Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
+            true,
+            false,
+            false,
+            Network::Regtest,
+            &[
+                "bcrt1qm6wqukenh7guu792lj2njgw9n78cmwsy8xy3z2",
+                "bcrt1q694twxtjn4nnrvnyvra769j0a23rllj5c6cgwp",
+                "bcrt1qhlac3c5ranv5w5emlnqs7wxhkxt8maelylcarp",
+            ],
+        );
+    }
+
+    // BIP86 `tr(key/86'/0'/0'/{0,1}/*)`
+    // Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
+    #[test]
+    fn test_bip86_template() {
+        let prvkey = bitcoin::bip32::Xpriv::from_str("xprv9s21ZrQH143K3GJpoapnV8SFfukcVBSfeCficPSGfubmSFDxo1kuHnLisriDvSnRRuL2Qrg5ggqHKNVpxR86QEC8w35uxmGoggxtQTPvfUu").unwrap();
+        check(
+            Bip86(prvkey, KeychainKind::External).build(Network::Bitcoin),
+            false,
+            true,
+            false,
+            Network::Bitcoin,
+            &[
+                "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
+                "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
+                "bc1p0d0rhyynq0awa9m8cqrcr8f5nxqx3aw29w4ru5u9my3h0sfygnzs9khxz8",
+            ],
+        );
+        check(
+            Bip86(prvkey, KeychainKind::Internal).build(Network::Bitcoin),
+            false,
+            true,
+            false,
+            Network::Bitcoin,
+            &[
+                "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7",
+                "bc1ptdg60grjk9t3qqcqczp4tlyy3z47yrx9nhlrjsmw36q5a72lhdrs9f00nj",
+                "bc1pgcwgsu8naxp7xlp5p7ufzs7emtfza2las7r2e7krzjhe5qj5xz2q88kmk5",
+            ],
+        );
+    }
+
+    // BIP86 public `tr(key/{0,1}/*)`
+    // Used addresses in test vector in https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki
+    #[test]
+    fn test_bip86_public_template() {
+        let pubkey = bitcoin::bip32::Xpub::from_str("xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ").unwrap();
+        let fingerprint = bitcoin::bip32::Fingerprint::from_str("73c5da0a").unwrap();
+        check(
+            Bip86Public(pubkey, fingerprint, KeychainKind::External).build(Network::Bitcoin),
+            false,
+            true,
+            false,
+            Network::Bitcoin,
+            &[
+                "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr",
+                "bc1p4qhjn9zdvkux4e44uhx8tc55attvtyu358kutcqkudyccelu0was9fqzwh",
+                "bc1p0d0rhyynq0awa9m8cqrcr8f5nxqx3aw29w4ru5u9my3h0sfygnzs9khxz8",
+            ],
+        );
+        check(
+            Bip86Public(pubkey, fingerprint, KeychainKind::Internal).build(Network::Bitcoin),
+            false,
+            true,
+            false,
+            Network::Bitcoin,
+            &[
+                "bc1p3qkhfews2uk44qtvauqyr2ttdsw7svhkl9nkm9s9c3x4ax5h60wqwruhk7",
+                "bc1ptdg60grjk9t3qqcqczp4tlyy3z47yrx9nhlrjsmw36q5a72lhdrs9f00nj",
+                "bc1pgcwgsu8naxp7xlp5p7ufzs7emtfza2las7r2e7krzjhe5qj5xz2q88kmk5",
+            ],
+        );
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/keys/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/keys/mod.rs.html new file mode 100644 index 0000000000..c4ad1fa450 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/keys/mod.rs.html @@ -0,0 +1,2019 @@ +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
+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
+
// 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.
+
+//! Key formats
+
+use crate::collections::HashSet;
+use alloc::string::{String, ToString};
+use alloc::vec::Vec;
+use core::any::TypeId;
+use core::fmt;
+use core::marker::PhantomData;
+use core::ops::Deref;
+use core::str::FromStr;
+
+use bitcoin::secp256k1::{self, Secp256k1, Signing};
+
+use bitcoin::bip32;
+use bitcoin::{key::XOnlyPublicKey, Network, PrivateKey, PublicKey};
+
+use miniscript::descriptor::{Descriptor, DescriptorXKey, Wildcard};
+pub use miniscript::descriptor::{
+    DescriptorPublicKey, DescriptorSecretKey, KeyMap, SinglePriv, SinglePub, SinglePubKey,
+    SortedMultiVec,
+};
+pub use miniscript::ScriptContext;
+use miniscript::{Miniscript, Terminal};
+
+use crate::descriptor::{CheckMiniscript, DescriptorError};
+use crate::wallet::utils::SecpCtx;
+
+#[cfg(feature = "keys-bip39")]
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+pub mod bip39;
+
+/// Set of valid networks for a key
+pub type ValidNetworks = HashSet<Network>;
+
+/// Create a set containing mainnet, testnet, signet, and regtest
+pub fn any_network() -> ValidNetworks {
+    vec![
+        Network::Bitcoin,
+        Network::Testnet,
+        Network::Regtest,
+        Network::Signet,
+    ]
+    .into_iter()
+    .collect()
+}
+/// Create a set only containing mainnet
+pub fn mainnet_network() -> ValidNetworks {
+    vec![Network::Bitcoin].into_iter().collect()
+}
+/// Create a set containing testnet and regtest
+pub fn test_networks() -> ValidNetworks {
+    vec![Network::Testnet, Network::Regtest, Network::Signet]
+        .into_iter()
+        .collect()
+}
+/// Compute the intersection of two sets
+pub fn merge_networks(a: &ValidNetworks, b: &ValidNetworks) -> ValidNetworks {
+    a.intersection(b).cloned().collect()
+}
+
+/// Container for public or secret keys
+#[derive(Debug)]
+pub enum DescriptorKey<Ctx: ScriptContext> {
+    #[doc(hidden)]
+    Public(DescriptorPublicKey, ValidNetworks, PhantomData<Ctx>),
+    #[doc(hidden)]
+    Secret(DescriptorSecretKey, ValidNetworks, PhantomData<Ctx>),
+}
+
+impl<Ctx: ScriptContext> DescriptorKey<Ctx> {
+    /// Create an instance given a public key and a set of valid networks
+    pub fn from_public(public: DescriptorPublicKey, networks: ValidNetworks) -> Self {
+        DescriptorKey::Public(public, networks, PhantomData)
+    }
+
+    /// Create an instance given a secret key and a set of valid networks
+    pub fn from_secret(secret: DescriptorSecretKey, networks: ValidNetworks) -> Self {
+        DescriptorKey::Secret(secret, networks, PhantomData)
+    }
+
+    /// Override the computed set of valid networks
+    pub fn override_valid_networks(self, networks: ValidNetworks) -> Self {
+        match self {
+            DescriptorKey::Public(key, _, _) => DescriptorKey::Public(key, networks, PhantomData),
+            DescriptorKey::Secret(key, _, _) => DescriptorKey::Secret(key, networks, PhantomData),
+        }
+    }
+
+    // This method is used internally by `bdk_wallet::fragment!` and `bdk_wallet::descriptor!`. It has to be
+    // public because it is effectively called by external crates once the macros are expanded,
+    // but since it is not meant to be part of the public api we hide it from the docs.
+    #[doc(hidden)]
+    pub fn extract(
+        self,
+        secp: &SecpCtx,
+    ) -> Result<(DescriptorPublicKey, KeyMap, ValidNetworks), KeyError> {
+        match self {
+            DescriptorKey::Public(public, valid_networks, _) => {
+                Ok((public, KeyMap::default(), valid_networks))
+            }
+            DescriptorKey::Secret(secret, valid_networks, _) => {
+                let mut key_map = KeyMap::new();
+
+                let public = secret
+                    .to_public(secp)
+                    .map_err(|e| miniscript::Error::Unexpected(e.to_string()))?;
+                key_map.insert(public.clone(), secret);
+
+                Ok((public, key_map, valid_networks))
+            }
+        }
+    }
+}
+
+/// Enum representation of the known valid [`ScriptContext`]s
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+pub enum ScriptContextEnum {
+    /// Legacy scripts
+    Legacy,
+    /// Segwitv0 scripts
+    Segwitv0,
+    /// Taproot scripts
+    Tap,
+}
+
+impl ScriptContextEnum {
+    /// Returns whether the script context is [`ScriptContextEnum::Legacy`]
+    pub fn is_legacy(&self) -> bool {
+        self == &ScriptContextEnum::Legacy
+    }
+
+    /// Returns whether the script context is [`ScriptContextEnum::Segwitv0`]
+    pub fn is_segwit_v0(&self) -> bool {
+        self == &ScriptContextEnum::Segwitv0
+    }
+
+    /// Returns whether the script context is [`ScriptContextEnum::Tap`]
+    pub fn is_taproot(&self) -> bool {
+        self == &ScriptContextEnum::Tap
+    }
+}
+
+/// Trait that adds extra useful methods to [`ScriptContext`]s
+pub trait ExtScriptContext: ScriptContext {
+    /// Returns the [`ScriptContext`] as a [`ScriptContextEnum`]
+    fn as_enum() -> ScriptContextEnum;
+
+    /// Returns whether the script context is [`Legacy`](miniscript::Legacy)
+    fn is_legacy() -> bool {
+        Self::as_enum().is_legacy()
+    }
+
+    /// Returns whether the script context is [`Segwitv0`](miniscript::Segwitv0)
+    fn is_segwit_v0() -> bool {
+        Self::as_enum().is_segwit_v0()
+    }
+
+    /// Returns whether the script context is [`Tap`](miniscript::Tap), aka Taproot or Segwit V1
+    fn is_taproot() -> bool {
+        Self::as_enum().is_taproot()
+    }
+}
+
+impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx {
+    fn as_enum() -> ScriptContextEnum {
+        match TypeId::of::<Ctx>() {
+            t if t == TypeId::of::<miniscript::Legacy>() => ScriptContextEnum::Legacy,
+            t if t == TypeId::of::<miniscript::Segwitv0>() => ScriptContextEnum::Segwitv0,
+            t if t == TypeId::of::<miniscript::Tap>() => ScriptContextEnum::Tap,
+            _ => unimplemented!("Unknown ScriptContext type"),
+        }
+    }
+}
+
+/// 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
+/// formats, like the mnemonics used by Electrum wallets, encode internally whether the wallet is
+/// legacy or segwit. Thus, trying to turn a valid legacy mnemonic into a `DescriptorKey`
+/// that would become part of a segwit descriptor should fail.
+///
+/// For key types that do care about this, the [`ExtScriptContext`] trait provides some useful
+/// methods that can be used to check at runtime which `Ctx` is being used.
+///
+/// For key types that can do this check statically (because they can only work within a
+/// single `Ctx`), the "specialized" trait can be implemented to make the compiler handle the type
+/// checking.
+///
+/// Keys also have control over the networks they support: constructing the return object with
+/// [`DescriptorKey::from_public`] or [`DescriptorKey::from_secret`] allows to specify a set of
+/// [`ValidNetworks`].
+///
+/// ## Examples
+///
+/// Key type valid in any context:
+///
+/// ```
+/// use bdk_wallet::bitcoin::PublicKey;
+///
+/// use bdk_wallet::keys::{DescriptorKey, IntoDescriptorKey, KeyError, ScriptContext};
+///
+/// pub struct MyKeyType {
+///     pubkey: PublicKey,
+/// }
+///
+/// impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for MyKeyType {
+///     fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+///         self.pubkey.into_descriptor_key()
+///     }
+/// }
+/// ```
+///
+/// Key type that is only valid on mainnet:
+///
+/// ```
+/// use bdk_wallet::bitcoin::PublicKey;
+///
+/// use bdk_wallet::keys::{
+///     mainnet_network, DescriptorKey, DescriptorPublicKey, IntoDescriptorKey, KeyError,
+///     ScriptContext, SinglePub, SinglePubKey,
+/// };
+///
+/// pub struct MyKeyType {
+///     pubkey: PublicKey,
+/// }
+///
+/// impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for MyKeyType {
+///     fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+///         Ok(DescriptorKey::from_public(
+///             DescriptorPublicKey::Single(SinglePub {
+///                 origin: None,
+///                 key: SinglePubKey::FullKey(self.pubkey),
+///             }),
+///             mainnet_network(),
+///         ))
+///     }
+/// }
+/// ```
+///
+/// Key type that internally encodes in which context it's valid. The context is checked at runtime:
+///
+/// ```
+/// use bdk_wallet::bitcoin::PublicKey;
+///
+/// use bdk_wallet::keys::{
+///     DescriptorKey, ExtScriptContext, IntoDescriptorKey, KeyError, ScriptContext,
+/// };
+///
+/// pub struct MyKeyType {
+///     is_legacy: bool,
+///     pubkey: PublicKey,
+/// }
+///
+/// impl<Ctx: ScriptContext + 'static> IntoDescriptorKey<Ctx> for MyKeyType {
+///     fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+///         if Ctx::is_legacy() == self.is_legacy {
+///             self.pubkey.into_descriptor_key()
+///         } else {
+///             Err(KeyError::InvalidScriptContext)
+///         }
+///     }
+/// }
+/// ```
+///
+/// Key type that can only work within [`miniscript::Segwitv0`] context. Only the specialized version
+/// of the trait is implemented.
+///
+/// This example deliberately fails to compile, to demonstrate how the compiler can catch when keys
+/// are misused. In this case, the "segwit-only" key is used to build a `pkh()` descriptor, which
+/// makes the compiler (correctly) fail.
+///
+/// ```compile_fail
+/// use bdk_wallet::bitcoin::PublicKey;
+/// use core::str::FromStr;
+///
+/// use bdk_wallet::keys::{DescriptorKey, IntoDescriptorKey, KeyError};
+///
+/// pub struct MySegwitOnlyKeyType {
+///     pubkey: PublicKey,
+/// }
+///
+/// impl IntoDescriptorKey<bdk_wallet::miniscript::Segwitv0> for MySegwitOnlyKeyType {
+///     fn into_descriptor_key(self) -> Result<DescriptorKey<bdk_wallet::miniscript::Segwitv0>, KeyError> {
+///         self.pubkey.into_descriptor_key()
+///     }
+/// }
+///
+/// let key = MySegwitOnlyKeyType {
+///     pubkey: PublicKey::from_str("...")?,
+/// };
+/// let (descriptor, _, _) = bdk_wallet::descriptor!(pkh(key))?;
+/// //                                               ^^^^^ changing this to `wpkh` would make it compile
+///
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+pub trait IntoDescriptorKey<Ctx: ScriptContext>: Sized {
+    /// Turn the key into a [`DescriptorKey`] within the requested [`ScriptContext`]
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError>;
+}
+
+/// Enum for extended keys that can be either `xprv` or `xpub`
+///
+/// An instance of [`ExtendedKey`] can be constructed from an [`Xpriv`](bip32::Xpriv)
+/// or an [`Xpub`](bip32::Xpub) by using the `From` trait.
+///
+/// Defaults to the [`Legacy`](miniscript::Legacy) context.
+pub enum ExtendedKey<Ctx: ScriptContext = miniscript::Legacy> {
+    /// A private extended key, aka an `xprv`
+    Private((bip32::Xpriv, PhantomData<Ctx>)),
+    /// A public extended key, aka an `xpub`
+    Public((bip32::Xpub, PhantomData<Ctx>)),
+}
+
+impl<Ctx: ScriptContext> ExtendedKey<Ctx> {
+    /// Return whether or not the key contains the private data
+    pub fn has_secret(&self) -> bool {
+        match self {
+            ExtendedKey::Private(_) => true,
+            ExtendedKey::Public(_) => false,
+        }
+    }
+
+    /// Transform the [`ExtendedKey`] into an [`Xpriv`](bip32::Xpriv) for the
+    /// given [`Network`], if the key contains the private data
+    pub fn into_xprv(self, network: Network) -> Option<bip32::Xpriv> {
+        match self {
+            ExtendedKey::Private((mut xprv, _)) => {
+                xprv.network = network;
+                Some(xprv)
+            }
+            ExtendedKey::Public(_) => None,
+        }
+    }
+
+    /// Transform the [`ExtendedKey`] into an [`Xpub`](bip32::Xpub) for the
+    /// given [`Network`]
+    pub fn into_xpub<C: Signing>(
+        self,
+        network: bitcoin::Network,
+        secp: &Secp256k1<C>,
+    ) -> bip32::Xpub {
+        let mut xpub = match self {
+            ExtendedKey::Private((xprv, _)) => bip32::Xpub::from_priv(secp, &xprv),
+            ExtendedKey::Public((xpub, _)) => xpub,
+        };
+
+        xpub.network = network;
+        xpub
+    }
+}
+
+impl<Ctx: ScriptContext> From<bip32::Xpub> for ExtendedKey<Ctx> {
+    fn from(xpub: bip32::Xpub) -> Self {
+        ExtendedKey::Public((xpub, PhantomData))
+    }
+}
+
+impl<Ctx: ScriptContext> From<bip32::Xpriv> for ExtendedKey<Ctx> {
+    fn from(xprv: bip32::Xpriv) -> Self {
+        ExtendedKey::Private((xprv, PhantomData))
+    }
+}
+
+/// Trait for keys that can be derived.
+///
+/// When extra metadata are provided, a [`DerivableKey`] can be transformed into a
+/// [`DescriptorKey`]: the trait [`IntoDescriptorKey`] is automatically implemented
+/// for `(DerivableKey, DerivationPath)` and
+/// `(DerivableKey, KeySource, DerivationPath)` tuples.
+///
+/// For key types that don't encode any indication about the path to use (like bip39), it's
+/// generally recommended to implement this trait instead of [`IntoDescriptorKey`]. The same
+/// rules regarding script context and valid networks apply.
+///
+/// ## Examples
+///
+/// Key types that can be directly converted into an [`Xpriv`] or
+/// an [`Xpub`] can implement only the required `into_extended_key()` method.
+///
+/// ```
+/// use bdk_wallet::bitcoin;
+/// use bdk_wallet::bitcoin::bip32;
+/// use bdk_wallet::keys::{DerivableKey, ExtendedKey, KeyError, ScriptContext};
+///
+/// struct MyCustomKeyType {
+///     key_data: bitcoin::PrivateKey,
+///     chain_code: [u8; 32],
+///     network: bitcoin::Network,
+/// }
+///
+/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
+///     fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+///         let xprv = bip32::Xpriv {
+///             network: self.network,
+///             depth: 0,
+///             parent_fingerprint: bip32::Fingerprint::default(),
+///             private_key: self.key_data.inner,
+///             chain_code: bip32::ChainCode::from(&self.chain_code),
+///             child_number: bip32::ChildNumber::Normal { index: 0 },
+///         };
+///
+///         xprv.into_extended_key()
+///     }
+/// }
+/// ```
+///
+/// Types that don't internally encode the [`Network`] in which they are valid need some extra
+/// steps to override the set of valid networks, otherwise only the network specified in the
+/// [`Xpriv`] or [`Xpub`] will be considered valid.
+///
+/// ```
+/// use bdk_wallet::bitcoin;
+/// use bdk_wallet::bitcoin::bip32;
+/// use bdk_wallet::keys::{
+///     any_network, DerivableKey, DescriptorKey, ExtendedKey, KeyError, ScriptContext,
+/// };
+///
+/// struct MyCustomKeyType {
+///     key_data: bitcoin::PrivateKey,
+///     chain_code: [u8; 32],
+/// }
+///
+/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
+///     fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+///         let xprv = bip32::Xpriv {
+///             network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
+///             depth: 0,
+///             parent_fingerprint: bip32::Fingerprint::default(),
+///             private_key: self.key_data.inner,
+///             chain_code: bip32::ChainCode::from(&self.chain_code),
+///             child_number: bip32::ChildNumber::Normal { index: 0 },
+///         };
+///
+///         xprv.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)?;
+///
+///         // Override the set of valid networks here
+///         Ok(descriptor_key.override_valid_networks(any_network()))
+///     }
+/// }
+/// ```
+///
+/// [`DerivationPath`]: (bip32::DerivationPath)
+/// [`Xpriv`]: (bip32::Xpriv)
+/// [`Xpub`]: (bip32::Xpub)
+pub trait DerivableKey<Ctx: ScriptContext = miniscript::Legacy>: Sized {
+    /// Consume `self` and turn it into an [`ExtendedKey`]
+    #[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_wallet::bitcoin::Network;
+use bdk_wallet::keys::{DerivableKey, ExtendedKey};
+use bdk_wallet::keys::bip39::{Mnemonic, Language};
+
+# fn main() -> Result<(), Box<dyn std::error::Error>> {
+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();
+# Ok(()) }
+```
+"##
+    )]
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError>;
+
+    /// Consume `self` and turn it into a [`DescriptorKey`] by adding the extra metadata, such as
+    /// key origin and derivation path
+    fn into_descriptor_key(
+        self,
+        origin: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        match self.into_extended_key()? {
+            ExtendedKey::Private((xprv, _)) => DescriptorSecretKey::XPrv(DescriptorXKey {
+                origin,
+                xkey: xprv,
+                derivation_path,
+                wildcard: Wildcard::Unhardened,
+            })
+            .into_descriptor_key(),
+            ExtendedKey::Public((xpub, _)) => DescriptorPublicKey::XPub(DescriptorXKey {
+                origin,
+                xkey: xpub,
+                derivation_path,
+                wildcard: Wildcard::Unhardened,
+            })
+            .into_descriptor_key(),
+        }
+    }
+}
+
+/// Identity conversion
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for ExtendedKey<Ctx> {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        Ok(self)
+    }
+}
+
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::Xpub {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        Ok(self.into())
+    }
+}
+
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::Xpriv {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        Ok(self.into())
+    }
+}
+
+/// Output of a [`GeneratableKey`] key generation
+pub struct GeneratedKey<K, Ctx: ScriptContext> {
+    key: K,
+    valid_networks: ValidNetworks,
+    phantom: PhantomData<Ctx>,
+}
+
+impl<K, Ctx: ScriptContext> GeneratedKey<K, Ctx> {
+    fn new(key: K, valid_networks: ValidNetworks) -> Self {
+        GeneratedKey {
+            key,
+            valid_networks,
+            phantom: PhantomData,
+        }
+    }
+
+    /// Consumes `self` and returns the key
+    pub fn into_key(self) -> K {
+        self.key
+    }
+}
+
+impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx> {
+    type Target = K;
+
+    fn deref(&self) -> &Self::Target {
+        &self.key
+    }
+}
+
+impl<K: Clone, Ctx: ScriptContext> Clone for GeneratedKey<K, Ctx> {
+    fn clone(&self) -> GeneratedKey<K, Ctx> {
+        GeneratedKey {
+            key: self.key.clone(),
+            valid_networks: self.valid_networks.clone(),
+            phantom: self.phantom,
+        }
+    }
+}
+
+// Make generated "derivable" keys themselves "derivable". Also make sure they are assigned the
+// right `valid_networks`.
+impl<Ctx, K> DerivableKey<Ctx> for GeneratedKey<K, Ctx>
+where
+    Ctx: ScriptContext,
+    K: DerivableKey<Ctx>,
+{
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        self.key.into_extended_key()
+    }
+
+    fn into_descriptor_key(
+        self,
+        origin: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let descriptor_key = self.key.into_descriptor_key(origin, derivation_path)?;
+        Ok(descriptor_key.override_valid_networks(self.valid_networks))
+    }
+}
+
+// Make generated keys directly usable in descriptors, and make sure they get assigned the right
+// `valid_networks`.
+impl<Ctx, K> IntoDescriptorKey<Ctx> for GeneratedKey<K, Ctx>
+where
+    Ctx: ScriptContext,
+    K: IntoDescriptorKey<Ctx>,
+{
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let desc_key = self.key.into_descriptor_key()?;
+        Ok(desc_key.override_valid_networks(self.valid_networks))
+    }
+}
+
+/// Trait for keys that can be generated
+///
+/// The same rules about [`ScriptContext`] and [`ValidNetworks`] from [`IntoDescriptorKey`] apply.
+///
+/// This trait is particularly useful when combined with [`DerivableKey`]: if `Self`
+/// 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`].
+pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
+    /// Type specifying the amount of entropy required e.g. `[u8;32]`
+    type Entropy: AsMut<[u8]> + Default;
+
+    /// Extra options required by the `generate_with_entropy`
+    type Options;
+    /// Returned error in case of failure
+    type Error: core::fmt::Debug;
+
+    /// Generate a key given the extra options and the entropy
+    fn generate_with_entropy(
+        options: Self::Options,
+        entropy: Self::Entropy,
+    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>;
+
+    /// Generate a key given the options with a random entropy
+    fn generate(options: Self::Options) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
+        use rand::{thread_rng, Rng};
+
+        let mut entropy = Self::Entropy::default();
+        thread_rng().fill(entropy.as_mut());
+        Self::generate_with_entropy(options, entropy)
+    }
+}
+
+/// Trait that allows generating a key with the default options
+///
+/// This trait is automatically implemented if the [`GeneratableKey::Options`] implements [`Default`].
+pub trait GeneratableDefaultOptions<Ctx>: GeneratableKey<Ctx>
+where
+    Ctx: ScriptContext,
+    <Self as GeneratableKey<Ctx>>::Options: Default,
+{
+    /// Generate a key with the default options and a given entropy
+    fn generate_with_entropy_default(
+        entropy: Self::Entropy,
+    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
+        Self::generate_with_entropy(Default::default(), entropy)
+    }
+
+    /// Generate a key with the default options and a random entropy
+    fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
+        Self::generate(Default::default())
+    }
+}
+
+/// Automatic implementation of [`GeneratableDefaultOptions`] for [`GeneratableKey`]s where
+/// `Options` implements `Default`
+impl<Ctx, K> GeneratableDefaultOptions<Ctx> for K
+where
+    Ctx: ScriptContext,
+    K: GeneratableKey<Ctx>,
+    <K as GeneratableKey<Ctx>>::Options: Default,
+{
+}
+
+impl<Ctx: ScriptContext> GeneratableKey<Ctx> for bip32::Xpriv {
+    type Entropy = [u8; 32];
+
+    type Options = ();
+    type Error = bip32::Error;
+
+    fn generate_with_entropy(
+        _: Self::Options,
+        entropy: Self::Entropy,
+    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
+        // pick a arbitrary network here, but say that we support all of them
+        let xprv = bip32::Xpriv::new_master(Network::Bitcoin, entropy.as_ref())?;
+        Ok(GeneratedKey::new(xprv, any_network()))
+    }
+}
+
+/// Options for generating a [`PrivateKey`]
+///
+/// Defaults to creating compressed keys, which save on-chain bytes and fees
+#[derive(Debug, Copy, Clone)]
+pub struct PrivateKeyGenerateOptions {
+    /// Whether the generated key should be "compressed" or not
+    pub compressed: bool,
+}
+
+impl Default for PrivateKeyGenerateOptions {
+    fn default() -> Self {
+        PrivateKeyGenerateOptions { compressed: true }
+    }
+}
+
+impl<Ctx: ScriptContext> GeneratableKey<Ctx> for PrivateKey {
+    type Entropy = [u8; secp256k1::constants::SECRET_KEY_SIZE];
+
+    type Options = PrivateKeyGenerateOptions;
+    type Error = bip32::Error;
+
+    fn generate_with_entropy(
+        options: Self::Options,
+        entropy: Self::Entropy,
+    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
+        // pick a arbitrary network here, but say that we support all of them
+        let inner = secp256k1::SecretKey::from_slice(&entropy)?;
+        let private_key = PrivateKey {
+            compressed: options.compressed,
+            network: Network::Bitcoin,
+            inner,
+        };
+
+        Ok(GeneratedKey::new(private_key, any_network()))
+    }
+}
+
+impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> IntoDescriptorKey<Ctx>
+    for (T, bip32::DerivationPath)
+{
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        self.0.into_descriptor_key(None, self.1)
+    }
+}
+
+impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> IntoDescriptorKey<Ctx>
+    for (T, bip32::KeySource, bip32::DerivationPath)
+{
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        self.0.into_descriptor_key(Some(self.1), self.2)
+    }
+}
+
+fn expand_multi_keys<Pk: IntoDescriptorKey<Ctx>, Ctx: ScriptContext>(
+    pks: Vec<Pk>,
+    secp: &SecpCtx,
+) -> Result<(Vec<DescriptorPublicKey>, KeyMap, ValidNetworks), KeyError> {
+    let (pks, key_maps_networks): (Vec<_>, Vec<_>) = pks
+        .into_iter()
+        .map(|key| key.into_descriptor_key()?.extract(secp))
+        .collect::<Result<Vec<_>, _>>()?
+        .into_iter()
+        .map(|(a, b, c)| (a, (b, c)))
+        .unzip();
+
+    let (key_map, valid_networks) = key_maps_networks.into_iter().fold(
+        (KeyMap::default(), any_network()),
+        |(mut keys_acc, net_acc), (key, net)| {
+            keys_acc.extend(key);
+            let net_acc = merge_networks(&net_acc, &net);
+
+            (keys_acc, net_acc)
+        },
+    );
+
+    Ok((pks, key_map, valid_networks))
+}
+
+// Used internally by `bdk_wallet::fragment!` to build `pk_k()` fragments
+#[doc(hidden)]
+pub fn make_pk<Pk: IntoDescriptorKey<Ctx>, Ctx: ScriptContext>(
+    descriptor_key: Pk,
+    secp: &SecpCtx,
+) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), DescriptorError> {
+    let (key, key_map, valid_networks) = descriptor_key.into_descriptor_key()?.extract(secp)?;
+    let minisc = Miniscript::from_ast(Terminal::PkK(key))?;
+
+    minisc.check_miniscript()?;
+
+    Ok((minisc, key_map, valid_networks))
+}
+
+// Used internally by `bdk_wallet::fragment!` to build `pk_h()` fragments
+#[doc(hidden)]
+pub fn make_pkh<Pk: IntoDescriptorKey<Ctx>, Ctx: ScriptContext>(
+    descriptor_key: Pk,
+    secp: &SecpCtx,
+) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), DescriptorError> {
+    let (key, key_map, valid_networks) = descriptor_key.into_descriptor_key()?.extract(secp)?;
+    let minisc = Miniscript::from_ast(Terminal::PkH(key))?;
+
+    minisc.check_miniscript()?;
+
+    Ok((minisc, key_map, valid_networks))
+}
+
+// Used internally by `bdk_wallet::fragment!` to build `multi()` fragments
+#[doc(hidden)]
+pub fn make_multi<
+    Pk: IntoDescriptorKey<Ctx>,
+    Ctx: ScriptContext,
+    V: Fn(usize, Vec<DescriptorPublicKey>) -> Terminal<DescriptorPublicKey, Ctx>,
+>(
+    thresh: usize,
+    variant: V,
+    pks: Vec<Pk>,
+    secp: &SecpCtx,
+) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), DescriptorError> {
+    let (pks, key_map, valid_networks) = expand_multi_keys(pks, secp)?;
+    let minisc = Miniscript::from_ast(variant(thresh, pks))?;
+
+    minisc.check_miniscript()?;
+
+    Ok((minisc, key_map, valid_networks))
+}
+
+// Used internally by `bdk_wallet::descriptor!` to build `sortedmulti()` fragments
+#[doc(hidden)]
+pub fn make_sortedmulti<Pk, Ctx, F>(
+    thresh: usize,
+    pks: Vec<Pk>,
+    build_desc: F,
+    secp: &SecpCtx,
+) -> Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>
+where
+    Pk: IntoDescriptorKey<Ctx>,
+    Ctx: ScriptContext,
+    F: Fn(
+        usize,
+        Vec<DescriptorPublicKey>,
+    ) -> Result<(Descriptor<DescriptorPublicKey>, PhantomData<Ctx>), DescriptorError>,
+{
+    let (pks, key_map, valid_networks) = expand_multi_keys(pks, secp)?;
+    let descriptor = build_desc(thresh, pks)?.0;
+
+    Ok((descriptor, key_map, valid_networks))
+}
+
+/// The "identity" conversion is used internally by some `bdk_wallet::fragment`s
+impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for DescriptorKey<Ctx> {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        Ok(self)
+    }
+}
+
+impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for DescriptorPublicKey {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let networks = match self {
+            DescriptorPublicKey::Single(_) => any_network(),
+            DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. })
+                if xkey.network == Network::Bitcoin =>
+            {
+                mainnet_network()
+            }
+            _ => test_networks(),
+        };
+
+        Ok(DescriptorKey::from_public(self, networks))
+    }
+}
+
+impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for PublicKey {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        DescriptorPublicKey::Single(SinglePub {
+            key: SinglePubKey::FullKey(self),
+            origin: None,
+        })
+        .into_descriptor_key()
+    }
+}
+
+impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for XOnlyPublicKey {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        DescriptorPublicKey::Single(SinglePub {
+            key: SinglePubKey::XOnly(self),
+            origin: None,
+        })
+        .into_descriptor_key()
+    }
+}
+
+impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for DescriptorSecretKey {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let networks = match &self {
+            DescriptorSecretKey::Single(sk) if sk.key.network == Network::Bitcoin => {
+                mainnet_network()
+            }
+            DescriptorSecretKey::XPrv(DescriptorXKey { xkey, .. })
+                if xkey.network == Network::Bitcoin =>
+            {
+                mainnet_network()
+            }
+            _ => test_networks(),
+        };
+
+        Ok(DescriptorKey::from_secret(self, networks))
+    }
+}
+
+impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for &'_ str {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        DescriptorSecretKey::from_str(self)
+            .map_err(|e| KeyError::Message(e.to_string()))?
+            .into_descriptor_key()
+    }
+}
+
+impl<Ctx: ScriptContext> IntoDescriptorKey<Ctx> for PrivateKey {
+    fn into_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        DescriptorSecretKey::Single(SinglePriv {
+            key: self,
+            origin: None,
+        })
+        .into_descriptor_key()
+    }
+}
+
+/// Errors thrown while working with [`keys`](crate::keys)
+#[derive(Debug)]
+pub enum KeyError {
+    /// The key cannot exist in the given script context
+    InvalidScriptContext,
+    /// The key is not valid for the given network
+    InvalidNetwork,
+    /// The key has an invalid checksum
+    InvalidChecksum,
+
+    /// Custom error message
+    Message(String),
+
+    /// BIP32 error
+    Bip32(bitcoin::bip32::Error),
+    /// Miniscript error
+    Miniscript(miniscript::Error),
+}
+
+impl From<miniscript::Error> for KeyError {
+    fn from(err: miniscript::Error) -> Self {
+        KeyError::Miniscript(err)
+    }
+}
+
+impl From<bip32::Error> for KeyError {
+    fn from(err: bip32::Error) -> Self {
+        KeyError::Bip32(err)
+    }
+}
+
+impl fmt::Display for KeyError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::InvalidScriptContext => write!(f, "Invalid script context"),
+            Self::InvalidNetwork => write!(f, "Invalid network"),
+            Self::InvalidChecksum => write!(f, "Invalid checksum"),
+            Self::Message(err) => write!(f, "{}", err),
+            Self::Bip32(err) => write!(f, "BIP32 error: {}", err),
+            Self::Miniscript(err) => write!(f, "Miniscript error: {}", err),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for KeyError {}
+
+#[cfg(test)]
+pub mod test {
+    use bitcoin::bip32;
+
+    use super::*;
+
+    pub const TEST_ENTROPY: [u8; 32] = [0xAA; 32];
+
+    #[test]
+    fn test_keys_generate_xprv() {
+        let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> =
+            bip32::Xpriv::generate_with_entropy_default(TEST_ENTROPY).unwrap();
+
+        assert_eq!(generated_xprv.valid_networks, any_network());
+        assert_eq!(generated_xprv.to_string(), "xprv9s21ZrQH143K4Xr1cJyqTvuL2FWR8eicgY9boWqMBv8MDVUZ65AXHnzBrK1nyomu6wdcabRgmGTaAKawvhAno1V5FowGpTLVx3jxzE5uk3Q");
+    }
+
+    #[test]
+    fn test_keys_generate_wif() {
+        let generated_wif: GeneratedKey<_, miniscript::Segwitv0> =
+            bitcoin::PrivateKey::generate_with_entropy_default(TEST_ENTROPY).unwrap();
+
+        assert_eq!(generated_wif.valid_networks, any_network());
+        assert_eq!(
+            generated_wif.to_string(),
+            "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch"
+        );
+    }
+
+    #[cfg(feature = "keys-bip39")]
+    #[test]
+    fn test_keys_wif_network_bip39() {
+        let xkey: ExtendedKey = bip39::Mnemonic::parse_in(
+            bip39::Language::English,
+            "jelly crash boy whisper mouse ecology tuna soccer memory million news short",
+        )
+        .unwrap()
+        .into_extended_key()
+        .unwrap();
+        let xprv = xkey.into_xprv(Network::Testnet).unwrap();
+
+        assert_eq!(xprv.network, Network::Testnet);
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/lib.rs.html new file mode 100644 index 0000000000..4f52b410d9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/lib.rs.html @@ -0,0 +1,97 @@ +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
+
#![doc = include_str!("../README.md")]
+// 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")
+)]
+#![no_std]
+#![warn(missing_docs)]
+
+#[cfg(feature = "std")]
+#[macro_use]
+extern crate std;
+
+#[doc(hidden)]
+#[macro_use]
+pub extern crate alloc;
+
+pub extern crate bitcoin;
+pub extern crate miniscript;
+extern crate serde;
+extern crate serde_json;
+
+#[cfg(feature = "keys-bip39")]
+extern crate bip39;
+
+pub mod descriptor;
+pub mod keys;
+pub mod psbt;
+pub(crate) mod types;
+pub mod wallet;
+
+pub use descriptor::template;
+pub use descriptor::HdKeyPaths;
+pub use types::*;
+pub use wallet::signer;
+pub use wallet::signer::SignOptions;
+pub use wallet::tx_builder::TxBuilder;
+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_wallet/psbt/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/psbt/mod.rs.html new file mode 100644 index 0000000000..42772f98ab --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/psbt/mod.rs.html @@ -0,0 +1,153 @@ +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
+
// 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.
+
+//! Additional functions on the `rust-bitcoin` `Psbt` structure.
+
+use alloc::vec::Vec;
+use bitcoin::Amount;
+use bitcoin::FeeRate;
+use bitcoin::Psbt;
+use bitcoin::TxOut;
+
+// TODO upstream the functions here to `rust-bitcoin`?
+
+/// Trait to add functions to extract utxos and calculate fees.
+pub trait PsbtUtils {
+    /// Get the `TxOut` for the specified input index, if it doesn't exist in the PSBT `None` is returned.
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
+
+    /// 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.
+    fn fee_amount(&self) -> Option<u64>;
+
+    /// The transaction's fee rate. This value will only be accurate if calculated AFTER the
+    /// `Psbt` is finalized and all witness/signature data is added to the
+    /// transaction.
+    /// If the PSBT is missing a TxOut for an input returns None.
+    fn fee_rate(&self) -> Option<FeeRate>;
+}
+
+impl PsbtUtils for Psbt {
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
+        let tx = &self.unsigned_tx;
+        let input = self.inputs.get(input_index)?;
+
+        match (&input.witness_utxo, &input.non_witness_utxo) {
+            (Some(_), _) => input.witness_utxo.clone(),
+            (_, Some(_)) => input.non_witness_utxo.as_ref().map(|in_tx| {
+                in_tx.output[tx.input[input_index].previous_output.vout as usize].clone()
+            }),
+            _ => None,
+        }
+    }
+
+    fn fee_amount(&self) -> Option<u64> {
+        let tx = &self.unsigned_tx;
+        let utxos: Option<Vec<TxOut>> = (0..tx.input.len()).map(|i| self.get_utxo_for(i)).collect();
+
+        utxos.map(|inputs| {
+            let input_amount: u64 = inputs.iter().map(|i| i.value.to_sat()).sum();
+            let output_amount: u64 = self
+                .unsigned_tx
+                .output
+                .iter()
+                .map(|o| o.value.to_sat())
+                .sum();
+            input_amount
+                .checked_sub(output_amount)
+                .expect("input amount must be greater than output amount")
+        })
+    }
+
+    fn fee_rate(&self) -> Option<FeeRate> {
+        let fee_amount = self.fee_amount();
+        let weight = self.clone().extract_tx().ok()?.weight();
+        fee_amount.map(|fee| Amount::from_sat(fee) / weight)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/types.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/types.rs.html new file mode 100644 index 0000000000..3542610aef --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/types.rs.html @@ -0,0 +1,273 @@ +types.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
+
// 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 alloc::boxed::Box;
+use core::convert::AsRef;
+
+use bdk_chain::ConfirmationTime;
+use bitcoin::blockdata::transaction::{OutPoint, Sequence, TxOut};
+use bitcoin::psbt;
+
+use serde::{Deserialize, Serialize};
+
+/// Types of keychains
+#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
+pub enum KeychainKind {
+    /// External keychain, used for deriving recipient addresses.
+    External = 0,
+    /// Internal keychain, used for deriving change addresses.
+    Internal = 1,
+}
+
+impl KeychainKind {
+    /// Return [`KeychainKind`] as a byte
+    pub fn as_byte(&self) -> u8 {
+        match self {
+            KeychainKind::External => b'e',
+            KeychainKind::Internal => b'i',
+        }
+    }
+}
+
+impl AsRef<[u8]> for KeychainKind {
+    fn as_ref(&self) -> &[u8] {
+        match self {
+            KeychainKind::External => b"e",
+            KeychainKind::Internal => b"i",
+        }
+    }
+}
+
+/// An unspent output owned by a [`Wallet`].
+///
+/// [`Wallet`]: crate::Wallet
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
+pub struct LocalOutput {
+    /// Reference to a transaction output
+    pub outpoint: OutPoint,
+    /// Transaction output
+    pub txout: TxOut,
+    /// Type of keychain
+    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`.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct WeightedUtxo {
+    /// 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.
+    ///
+    /// [weight units]: https://en.bitcoin.it/wiki/Weight_units
+    pub satisfaction_weight: usize,
+    /// The UTXO
+    pub utxo: Utxo,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+/// An unspent transaction output (UTXO).
+pub enum Utxo {
+    /// A UTXO owned by the local wallet.
+    Local(LocalOutput),
+    /// A UTXO owned by another wallet.
+    Foreign {
+        /// The location of the output.
+        outpoint: OutPoint,
+        /// The nSequence value to set for this input.
+        sequence: Option<Sequence>,
+        /// The information about the input we require to add it to a PSBT.
+        // Box it to stop the type being too big.
+        psbt_input: Box<psbt::Input>,
+    },
+}
+
+impl Utxo {
+    /// Get the location of the UTXO
+    pub fn outpoint(&self) -> OutPoint {
+        match &self {
+            Utxo::Local(local) => local.outpoint,
+            Utxo::Foreign { outpoint, .. } => *outpoint,
+        }
+    }
+
+    /// Get the `TxOut` of the UTXO
+    pub fn txout(&self) -> &TxOut {
+        match &self {
+            Utxo::Local(local) => &local.txout,
+            Utxo::Foreign {
+                outpoint,
+                psbt_input,
+                ..
+            } => {
+                if let Some(prev_tx) = &psbt_input.non_witness_utxo {
+                    return &prev_tx.output[outpoint.vout as usize];
+                }
+
+                if let Some(txout) = &psbt_input.witness_utxo {
+                    return txout;
+                }
+
+                unreachable!("Foreign UTXOs will always have one of these set")
+            }
+        }
+    }
+
+    /// Get the sequence number if an explicit sequence number has to be set for this input.
+    pub fn sequence(&self) -> Option<Sequence> {
+        match self {
+            Utxo::Local(_) => None,
+            Utxo::Foreign { sequence, .. } => *sequence,
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/coin_selection.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/coin_selection.rs.html new file mode 100644 index 0000000000..de081a0928 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/coin_selection.rs.html @@ -0,0 +1,3207 @@ +coin_selection.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
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+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
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+
// 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.
+
+//! Coin selection
+//!
+//! This module provides the trait [`CoinSelectionAlgorithm`] that can be implemented to
+//! define custom coin selection algorithms.
+//!
+//! You can specify a custom coin selection algorithm through the [`coin_selection`] method on
+//! [`TxBuilder`]. [`DefaultCoinSelectionAlgorithm`] aliases the coin selection algorithm that will
+//! be used if it is not explicitly set.
+//!
+//! [`TxBuilder`]: super::tx_builder::TxBuilder
+//! [`coin_selection`]: super::tx_builder::TxBuilder::coin_selection
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bdk_wallet::wallet::{self, ChangeSet, coin_selection::*, coin_selection};
+//! # use bdk_wallet::wallet::error::CreateTxError;
+//! # use bdk_persist::PersistBackend;
+//! # use bdk_wallet::*;
+//! # use bdk_wallet::wallet::coin_selection::decide_change;
+//! # use anyhow::Error;
+//! #[derive(Debug)]
+//! struct AlwaysSpendEverything;
+//!
+//! impl CoinSelectionAlgorithm for AlwaysSpendEverything {
+//!     fn coin_select(
+//!         &self,
+//!         required_utxos: Vec<WeightedUtxo>,
+//!         optional_utxos: Vec<WeightedUtxo>,
+//!         fee_rate: FeeRate,
+//!         target_amount: u64,
+//!         drain_script: &Script,
+//!     ) -> Result<CoinSelectionResult, coin_selection::Error> {
+//!         let mut selected_amount = 0;
+//!         let mut additional_weight = Weight::ZERO;
+//!         let all_utxos_selected = required_utxos
+//!             .into_iter()
+//!             .chain(optional_utxos)
+//!             .scan(
+//!                 (&mut selected_amount, &mut additional_weight),
+//!                 |(selected_amount, additional_weight), weighted_utxo| {
+//!                     **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
+//!                     **additional_weight += Weight::from_wu(
+//!                         (TxIn::default().segwit_weight().to_wu()
+//!                             + weighted_utxo.satisfaction_weight as u64)
+//!                             as u64,
+//!                     );
+//!                     Some(weighted_utxo.utxo)
+//!                 },
+//!             )
+//!             .collect::<Vec<_>>();
+//!         let additional_fees = (fee_rate * additional_weight).to_sat();
+//!         let amount_needed_with_fees = additional_fees + target_amount;
+//!         if selected_amount < amount_needed_with_fees {
+//!             return Err(coin_selection::Error::InsufficientFunds {
+//!                 needed: amount_needed_with_fees,
+//!                 available: selected_amount,
+//!             });
+//!         }
+//!
+//!         let remaining_amount = selected_amount - amount_needed_with_fees;
+//!
+//!         let excess = decide_change(remaining_amount, fee_rate, drain_script);
+//!
+//!         Ok(CoinSelectionResult {
+//!             selected: all_utxos_selected,
+//!             fee_amount: additional_fees,
+//!             excess,
+//!         })
+//!     }
+//! }
+//!
+//! # let mut wallet = doctest_wallet!();
+//! // create wallet, sync, ...
+//!
+//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
+//!     .unwrap()
+//!     .require_network(Network::Testnet)
+//!     .unwrap();
+//! let psbt = {
+//!     let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
+//!     builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
+//!     builder.finish()?
+//! };
+//!
+//! // inspect, sign, broadcast, ...
+//!
+//! # Ok::<(), anyhow::Error>(())
+//! ```
+
+use crate::chain::collections::HashSet;
+use crate::wallet::utils::IsDust;
+use crate::Utxo;
+use crate::WeightedUtxo;
+use bitcoin::FeeRate;
+
+use alloc::vec::Vec;
+use bitcoin::consensus::encode::serialize;
+use bitcoin::OutPoint;
+use bitcoin::TxIn;
+use bitcoin::{Script, Weight};
+
+use core::convert::TryInto;
+use core::fmt::{self, Formatter};
+use rand::seq::SliceRandom;
+
+/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
+/// overridden
+pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
+
+/// Errors that can be thrown by the [`coin_selection`](crate::wallet::coin_selection) module
+#[derive(Debug)]
+pub enum Error {
+    /// Wallet's UTXO set is not enough to cover recipient's requested plus fee
+    InsufficientFunds {
+        /// Sats needed for some transaction
+        needed: u64,
+        /// Sats available for spending
+        available: u64,
+    },
+    /// Branch and bound coin selection tries to avoid needing a change by finding the right inputs for
+    /// the desired outputs plus fee, if there is not such combination this error is thrown
+    BnBNoExactMatch,
+    /// Branch and bound coin selection possible attempts with sufficiently big UTXO set could grow
+    /// exponentially, thus a limit is set, and when hit, this error is thrown
+    BnBTotalTriesExceeded,
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::InsufficientFunds { needed, available } => write!(
+                f,
+                "Insufficient funds: {} sat available of {} sat needed",
+                available, needed
+            ),
+            Self::BnBTotalTriesExceeded => {
+                write!(f, "Branch and bound coin selection: total tries exceeded")
+            }
+            Self::BnBNoExactMatch => write!(f, "Branch and bound coin selection: not exact match"),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for Error {}
+
+#[derive(Debug)]
+/// Remaining amount after performing coin selection
+pub enum Excess {
+    /// It's not possible to create spendable output from excess using the current drain output
+    NoChange {
+        /// Threshold to consider amount as dust for this particular change script_pubkey
+        dust_threshold: u64,
+        /// Exceeding amount of current selection over outgoing value and fee costs
+        remaining_amount: u64,
+        /// The calculated fee for the drain TxOut with the selected script_pubkey
+        change_fee: u64,
+    },
+    /// It's possible to create spendable output from excess using the current drain output
+    Change {
+        /// Effective amount available to create change after deducting the change output fee
+        amount: u64,
+        /// The deducted change output fee
+        fee: u64,
+    },
+}
+
+/// Result of a successful coin selection
+#[derive(Debug)]
+pub struct CoinSelectionResult {
+    /// List of outputs selected for use as inputs
+    pub selected: Vec<Utxo>,
+    /// Total fee amount for the selected utxos in satoshis
+    pub fee_amount: u64,
+    /// Remaining amount after deducing fees and outgoing outputs
+    pub excess: Excess,
+}
+
+impl CoinSelectionResult {
+    /// The total value of the inputs selected.
+    pub fn selected_amount(&self) -> u64 {
+        self.selected.iter().map(|u| u.txout().value.to_sat()).sum()
+    }
+
+    /// The total value of the inputs selected from the local wallet.
+    pub fn local_selected_amount(&self) -> u64 {
+        self.selected
+            .iter()
+            .filter_map(|u| match u {
+                Utxo::Local(_) => Some(u.txout().value.to_sat()),
+                _ => None,
+            })
+            .sum()
+    }
+}
+
+/// Trait for generalized coin selection algorithms
+///
+/// This trait can be implemented to make the [`Wallet`](super::Wallet) use a customized coin
+/// selection algorithm when it creates transactions.
+///
+/// For an example see [this module](crate::wallet::coin_selection)'s documentation.
+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
+    ///               details for a specific UTXO
+    /// - `required_utxos`: the utxos that must be spent regardless of `target_amount` with their
+    ///                     weight cost
+    /// - `optional_utxos`: the remaining available utxos to satisfy `target_amount` with their
+    ///                     weight cost
+    /// - `fee_rate`: fee rate to use
+    /// - `target_amount`: the outgoing amount in satoshis and the fees already
+    ///                    accumulated from added outputs and transaction’s header.
+    /// - `drain_script`: the script to use in case of change
+    #[allow(clippy::too_many_arguments)]
+    fn coin_select(
+        &self,
+        required_utxos: Vec<WeightedUtxo>,
+        optional_utxos: Vec<WeightedUtxo>,
+        fee_rate: FeeRate,
+        target_amount: u64,
+        drain_script: &Script,
+    ) -> Result<CoinSelectionResult, Error>;
+}
+
+/// 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.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct LargestFirstCoinSelection;
+
+impl CoinSelectionAlgorithm for LargestFirstCoinSelection {
+    fn coin_select(
+        &self,
+        required_utxos: Vec<WeightedUtxo>,
+        mut optional_utxos: Vec<WeightedUtxo>,
+        fee_rate: FeeRate,
+        target_amount: u64,
+        drain_script: &Script,
+    ) -> Result<CoinSelectionResult, Error> {
+        // We put the "required UTXOs" first and make sure the optional UTXOs are sorted,
+        // initially smallest to largest, before being reversed with `.rev()`.
+        let utxos = {
+            optional_utxos.sort_unstable_by_key(|wu| wu.utxo.txout().value);
+            required_utxos
+                .into_iter()
+                .map(|utxo| (true, utxo))
+                .chain(optional_utxos.into_iter().rev().map(|utxo| (false, utxo)))
+        };
+
+        select_sorted_utxos(utxos, fee_rate, target_amount, drain_script)
+    }
+}
+
+/// 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.
+#[derive(Debug, Default, Clone, Copy)]
+pub struct OldestFirstCoinSelection;
+
+impl CoinSelectionAlgorithm for OldestFirstCoinSelection {
+    fn coin_select(
+        &self,
+        required_utxos: Vec<WeightedUtxo>,
+        mut optional_utxos: Vec<WeightedUtxo>,
+        fee_rate: FeeRate,
+        target_amount: u64,
+        drain_script: &Script,
+    ) -> Result<CoinSelectionResult, Error> {
+        // 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 &wu.utxo {
+                Utxo::Local(local) => Some(local.confirmation_time),
+                Utxo::Foreign { .. } => None,
+            });
+
+            required_utxos
+                .into_iter()
+                .map(|utxo| (true, utxo))
+                .chain(optional_utxos.into_iter().map(|utxo| (false, utxo)))
+        };
+
+        select_sorted_utxos(utxos, fee_rate, target_amount, drain_script)
+    }
+}
+
+/// Decide if change can be created
+///
+/// - `remaining_amount`: the amount in which the selected coins exceed the target amount
+/// - `fee_rate`: required fee rate for the current selection
+/// - `drain_script`: script to consider change creation
+pub fn decide_change(remaining_amount: u64, fee_rate: FeeRate, drain_script: &Script) -> Excess {
+    // drain_output_len = size(len(script_pubkey)) + len(script_pubkey) + size(output_value)
+    let drain_output_len = serialize(drain_script).len() + 8usize;
+    let change_fee =
+        (fee_rate * Weight::from_vb(drain_output_len as u64).expect("overflow occurred")).to_sat();
+    let drain_val = remaining_amount.saturating_sub(change_fee);
+
+    if drain_val.is_dust(drain_script) {
+        let dust_threshold = drain_script.dust_value().to_sat();
+        Excess::NoChange {
+            dust_threshold,
+            change_fee,
+            remaining_amount,
+        }
+    } else {
+        Excess::Change {
+            amount: drain_val,
+            fee: change_fee,
+        }
+    }
+}
+
+fn select_sorted_utxos(
+    utxos: impl Iterator<Item = (bool, WeightedUtxo)>,
+    fee_rate: FeeRate,
+    target_amount: u64,
+    drain_script: &Script,
+) -> Result<CoinSelectionResult, Error> {
+    let mut selected_amount = 0;
+    let mut fee_amount = 0;
+    let selected = utxos
+        .scan(
+            (&mut selected_amount, &mut fee_amount),
+            |(selected_amount, fee_amount), (must_use, weighted_utxo)| {
+                if must_use || **selected_amount < target_amount + **fee_amount {
+                    **fee_amount += (fee_rate
+                        * Weight::from_wu(
+                            TxIn::default().segwit_weight().to_wu()
+                                + weighted_utxo.satisfaction_weight as u64,
+                        ))
+                    .to_sat();
+                    **selected_amount += weighted_utxo.utxo.txout().value.to_sat();
+                    Some(weighted_utxo.utxo)
+                } else {
+                    None
+                }
+            },
+        )
+        .collect::<Vec<_>>();
+
+    let amount_needed_with_fees = target_amount + fee_amount;
+    if selected_amount < amount_needed_with_fees {
+        return Err(Error::InsufficientFunds {
+            needed: amount_needed_with_fees,
+            available: selected_amount,
+        });
+    }
+
+    let remaining_amount = selected_amount - amount_needed_with_fees;
+
+    let excess = decide_change(remaining_amount, fee_rate, drain_script);
+
+    Ok(CoinSelectionResult {
+        selected,
+        fee_amount,
+        excess,
+    })
+}
+
+#[derive(Debug, Clone)]
+// Adds fee information to an UTXO.
+struct OutputGroup {
+    weighted_utxo: WeightedUtxo,
+    // Amount of fees for spending a certain utxo, calculated using a certain FeeRate
+    fee: u64,
+    // The effective value of the UTXO, i.e., the utxo value minus the fee for spending it
+    effective_value: i64,
+}
+
+impl OutputGroup {
+    fn new(weighted_utxo: WeightedUtxo, fee_rate: FeeRate) -> Self {
+        let fee = (fee_rate
+            * Weight::from_wu(
+                TxIn::default().segwit_weight().to_wu() + weighted_utxo.satisfaction_weight as u64,
+            ))
+        .to_sat();
+        let effective_value = weighted_utxo.utxo.txout().value.to_sat() as i64 - fee as i64;
+        OutputGroup {
+            weighted_utxo,
+            fee,
+            effective_value,
+        }
+    }
+}
+
+/// 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, Clone)]
+pub struct BranchAndBoundCoinSelection {
+    size_of_change: u64,
+}
+
+impl Default for BranchAndBoundCoinSelection {
+    fn default() -> Self {
+        Self {
+            // P2WPKH cost of change -> value (8 bytes) + script len (1 bytes) + script (22 bytes)
+            size_of_change: 8 + 1 + 22,
+        }
+    }
+}
+
+impl BranchAndBoundCoinSelection {
+    /// Create new instance with target size for change output
+    pub fn new(size_of_change: u64) -> Self {
+        Self { size_of_change }
+    }
+}
+
+const BNB_TOTAL_TRIES: usize = 100_000;
+
+impl CoinSelectionAlgorithm for BranchAndBoundCoinSelection {
+    fn coin_select(
+        &self,
+        required_utxos: Vec<WeightedUtxo>,
+        optional_utxos: Vec<WeightedUtxo>,
+        fee_rate: FeeRate,
+        target_amount: u64,
+        drain_script: &Script,
+    ) -> Result<CoinSelectionResult, Error> {
+        // Mapping every (UTXO, usize) to an output group
+        let required_utxos: Vec<OutputGroup> = required_utxos
+            .into_iter()
+            .map(|u| OutputGroup::new(u, fee_rate))
+            .collect();
+
+        // Mapping every (UTXO, usize) to an output group, filtering UTXOs with a negative
+        // effective value
+        let optional_utxos: Vec<OutputGroup> = optional_utxos
+            .into_iter()
+            .map(|u| OutputGroup::new(u, fee_rate))
+            .filter(|u| u.effective_value.is_positive())
+            .collect();
+
+        let curr_value = required_utxos
+            .iter()
+            .fold(0, |acc, x| acc + x.effective_value);
+
+        let curr_available_value = optional_utxos
+            .iter()
+            .fold(0, |acc, x| acc + x.effective_value);
+
+        let cost_of_change =
+            (Weight::from_vb(self.size_of_change).expect("overflow occurred") * fee_rate).to_sat();
+
+        // `curr_value` and `curr_available_value` are both the sum of *effective_values* of
+        // the UTXOs. For the optional UTXOs (curr_available_value) we filter out UTXOs with
+        // negative effective value, so it will always be positive.
+        //
+        // Since we are required to spend the required UTXOs (curr_value) we have to consider
+        // all their effective values, even when negative, which means that curr_value could
+        // be negative as well.
+        //
+        // If the sum of curr_value and curr_available_value is negative or lower than our target,
+        // we can immediately exit with an error, as it's guaranteed we will never find a solution
+        // if we actually run the BnB.
+        let total_value: Result<u64, _> = (curr_available_value + curr_value).try_into();
+        match total_value {
+            Ok(v) if v >= target_amount => {}
+            _ => {
+                // Assume we spend all the UTXOs we can (all the required + all the optional with
+                // positive effective value), sum their value and their fee cost.
+                let (utxo_fees, utxo_value) = required_utxos
+                    .iter()
+                    .chain(optional_utxos.iter())
+                    .fold((0, 0), |(mut fees, mut value), utxo| {
+                        fees += utxo.fee;
+                        value += utxo.weighted_utxo.utxo.txout().value.to_sat();
+
+                        (fees, value)
+                    });
+
+                // Add to the target the fee cost of the UTXOs
+                return Err(Error::InsufficientFunds {
+                    needed: target_amount + utxo_fees,
+                    available: utxo_value,
+                });
+            }
+        }
+
+        let target_amount = target_amount
+            .try_into()
+            .expect("Bitcoin amount to fit into i64");
+
+        if curr_value > target_amount {
+            // remaining_amount can't be negative as that would mean the
+            // selection wasn't successful
+            // target_amount = amount_needed + (fee_amount - vin_fees)
+            let remaining_amount = (curr_value - target_amount) as u64;
+
+            let excess = decide_change(remaining_amount, fee_rate, drain_script);
+
+            return Ok(BranchAndBoundCoinSelection::calculate_cs_result(
+                vec![],
+                required_utxos,
+                excess,
+            ));
+        }
+
+        Ok(self
+            .bnb(
+                required_utxos.clone(),
+                optional_utxos.clone(),
+                curr_value,
+                curr_available_value,
+                target_amount,
+                cost_of_change,
+                drain_script,
+                fee_rate,
+            )
+            .unwrap_or_else(|_| {
+                self.single_random_draw(
+                    required_utxos,
+                    optional_utxos,
+                    curr_value,
+                    target_amount,
+                    drain_script,
+                    fee_rate,
+                )
+            }))
+    }
+}
+
+impl BranchAndBoundCoinSelection {
+    // TODO: make this more Rust-onic :)
+    // (And perhaps refactor with less arguments?)
+    #[allow(clippy::too_many_arguments)]
+    fn bnb(
+        &self,
+        required_utxos: Vec<OutputGroup>,
+        mut optional_utxos: Vec<OutputGroup>,
+        mut curr_value: i64,
+        mut curr_available_value: i64,
+        target_amount: i64,
+        cost_of_change: u64,
+        drain_script: &Script,
+        fee_rate: FeeRate,
+    ) -> Result<CoinSelectionResult, Error> {
+        // current_selection[i] will contain true if we are using optional_utxos[i],
+        // false otherwise. Note that current_selection.len() could be less than
+        // optional_utxos.len(), it just means that we still haven't decided if we should keep
+        // certain optional_utxos or not.
+        let mut current_selection: Vec<bool> = Vec::with_capacity(optional_utxos.len());
+
+        // Sort the utxo_pool
+        optional_utxos.sort_unstable_by_key(|a| a.effective_value);
+        optional_utxos.reverse();
+
+        // Contains the best selection we found
+        let mut best_selection = Vec::new();
+        let mut best_selection_value = None;
+
+        // Depth First search loop for choosing the UTXOs
+        for _ in 0..BNB_TOTAL_TRIES {
+            // Conditions for starting a backtrack
+            let mut backtrack = false;
+            // Cannot possibly reach target with the amount remaining in the curr_available_value,
+            // or the selected value is out of range.
+            // Go back and try other branch
+            if curr_value + curr_available_value < target_amount
+                || curr_value > target_amount + cost_of_change as i64
+            {
+                backtrack = true;
+            } else if curr_value >= target_amount {
+                // Selected value is within range, there's no point in going forward. Start
+                // backtracking
+                backtrack = true;
+
+                // If we found a solution better than the previous one, or if there wasn't previous
+                // solution, update the best solution
+                if best_selection_value.is_none() || curr_value < best_selection_value.unwrap() {
+                    best_selection.clone_from(&current_selection);
+                    best_selection_value = Some(curr_value);
+                }
+
+                // If we found a perfect match, break here
+                if curr_value == target_amount {
+                    break;
+                }
+            }
+
+            // Backtracking, moving backwards
+            if backtrack {
+                // Walk backwards to find the last included UTXO that still needs to have its omission branch traversed.
+                while let Some(false) = current_selection.last() {
+                    current_selection.pop();
+                    curr_available_value += optional_utxos[current_selection.len()].effective_value;
+                }
+
+                if current_selection.last_mut().is_none() {
+                    // We have walked back to the first utxo and no branch is untraversed. All solutions searched
+                    // If best selection is empty, then there's no exact match
+                    if best_selection.is_empty() {
+                        return Err(Error::BnBNoExactMatch);
+                    }
+                    break;
+                }
+
+                if let Some(c) = current_selection.last_mut() {
+                    // Output was included on previous iterations, try excluding now.
+                    *c = false;
+                }
+
+                let utxo = &optional_utxos[current_selection.len() - 1];
+                curr_value -= utxo.effective_value;
+            } else {
+                // Moving forwards, continuing down this branch
+                let utxo = &optional_utxos[current_selection.len()];
+
+                // Remove this utxo from the curr_available_value utxo amount
+                curr_available_value -= utxo.effective_value;
+
+                // Inclusion branch first (Largest First Exploration)
+                current_selection.push(true);
+                curr_value += utxo.effective_value;
+            }
+        }
+
+        // Check for solution
+        if best_selection.is_empty() {
+            return Err(Error::BnBTotalTriesExceeded);
+        }
+
+        // Set output set
+        let selected_utxos = optional_utxos
+            .into_iter()
+            .zip(best_selection)
+            .filter_map(|(optional, is_in_best)| if is_in_best { Some(optional) } else { None })
+            .collect::<Vec<OutputGroup>>();
+
+        let selected_amount = best_selection_value.unwrap();
+
+        // remaining_amount can't be negative as that would mean the
+        // selection wasn't successful
+        // target_amount = amount_needed + (fee_amount - vin_fees)
+        let remaining_amount = (selected_amount - target_amount) as u64;
+
+        let excess = decide_change(remaining_amount, fee_rate, drain_script);
+
+        Ok(BranchAndBoundCoinSelection::calculate_cs_result(
+            selected_utxos,
+            required_utxos,
+            excess,
+        ))
+    }
+
+    #[allow(clippy::too_many_arguments)]
+    fn single_random_draw(
+        &self,
+        required_utxos: Vec<OutputGroup>,
+        mut optional_utxos: Vec<OutputGroup>,
+        curr_value: i64,
+        target_amount: i64,
+        drain_script: &Script,
+        fee_rate: FeeRate,
+    ) -> CoinSelectionResult {
+        optional_utxos.shuffle(&mut rand::thread_rng());
+        let selected_utxos = optional_utxos.into_iter().fold(
+            (curr_value, vec![]),
+            |(mut amount, mut utxos), utxo| {
+                if amount >= target_amount {
+                    (amount, utxos)
+                } else {
+                    amount += utxo.effective_value;
+                    utxos.push(utxo);
+                    (amount, utxos)
+                }
+            },
+        );
+
+        // remaining_amount can't be negative as that would mean the
+        // selection wasn't successful
+        // target_amount = amount_needed + (fee_amount - vin_fees)
+        let remaining_amount = (selected_utxos.0 - target_amount) as u64;
+
+        let excess = decide_change(remaining_amount, fee_rate, drain_script);
+
+        BranchAndBoundCoinSelection::calculate_cs_result(selected_utxos.1, required_utxos, excess)
+    }
+
+    fn calculate_cs_result(
+        mut selected_utxos: Vec<OutputGroup>,
+        mut required_utxos: Vec<OutputGroup>,
+        excess: Excess,
+    ) -> CoinSelectionResult {
+        selected_utxos.append(&mut required_utxos);
+        let fee_amount = selected_utxos.iter().map(|u| u.fee).sum::<u64>();
+        let selected = selected_utxos
+            .into_iter()
+            .map(|u| u.weighted_utxo.utxo)
+            .collect::<Vec<_>>();
+
+        CoinSelectionResult {
+            selected,
+            fee_amount,
+            excess,
+        }
+    }
+}
+
+/// Remove duplicate UTXOs.
+///
+/// If a UTXO appears in both `required` and `optional`, the appearance in `required` is kept.
+pub(crate) fn filter_duplicates<I>(required: I, optional: I) -> (I, I)
+where
+    I: IntoIterator<Item = WeightedUtxo> + FromIterator<WeightedUtxo>,
+{
+    let mut visited = HashSet::<OutPoint>::new();
+    let required = required
+        .into_iter()
+        .filter(|utxo| visited.insert(utxo.utxo.outpoint()))
+        .collect::<I>();
+    let optional = optional
+        .into_iter()
+        .filter(|utxo| visited.insert(utxo.utxo.outpoint()))
+        .collect::<I>();
+    (required, optional)
+}
+
+#[cfg(test)]
+mod test {
+    use assert_matches::assert_matches;
+    use core::str::FromStr;
+
+    use bdk_chain::ConfirmationTime;
+    use bitcoin::{Amount, ScriptBuf, TxIn, TxOut};
+
+    use super::*;
+    use crate::types::*;
+    use crate::wallet::coin_selection::filter_duplicates;
+
+    use rand::rngs::StdRng;
+    use rand::seq::SliceRandom;
+    use rand::{Rng, RngCore, SeedableRng};
+
+    // signature len (1WU) + signature and sighash (72WU)
+    // + pubkey len (1WU) + pubkey (33WU)
+    const P2WPKH_SATISFACTION_SIZE: usize = 1 + 72 + 1 + 33;
+
+    const FEE_AMOUNT: u64 = 50;
+
+    fn utxo(value: u64, index: u32, confirmation_time: ConfirmationTime) -> WeightedUtxo {
+        assert!(index < 10);
+        let outpoint = OutPoint::from_str(&format!(
+            "000000000000000000000000000000000000000000000000000000000000000{}:0",
+            index
+        ))
+        .unwrap();
+        WeightedUtxo {
+            satisfaction_weight: P2WPKH_SATISFACTION_SIZE,
+            utxo: Utxo::Local(LocalOutput {
+                outpoint,
+                txout: TxOut {
+                    value: Amount::from_sat(value),
+                    script_pubkey: ScriptBuf::new(),
+                },
+                keychain: KeychainKind::External,
+                is_spent: false,
+                derivation_index: 42,
+                confirmation_time,
+            }),
+        }
+    }
+
+    fn get_test_utxos() -> Vec<WeightedUtxo> {
+        vec![
+            utxo(100_000, 0, ConfirmationTime::Unconfirmed { last_seen: 0 }),
+            utxo(
+                FEE_AMOUNT - 40,
+                1,
+                ConfirmationTime::Unconfirmed { last_seen: 0 },
+            ),
+            utxo(200_000, 2, ConfirmationTime::Unconfirmed { last_seen: 0 }),
+        ]
+    }
+
+    fn get_oldest_first_test_utxos() -> Vec<WeightedUtxo> {
+        // ensure utxos are from different tx
+        let utxo1 = utxo(
+            120_000,
+            1,
+            ConfirmationTime::Confirmed {
+                height: 1,
+                time: 1231006505,
+            },
+        );
+        let utxo2 = utxo(
+            80_000,
+            2,
+            ConfirmationTime::Confirmed {
+                height: 2,
+                time: 1231006505,
+            },
+        );
+        let utxo3 = utxo(
+            300_000,
+            3,
+            ConfirmationTime::Confirmed {
+                height: 3,
+                time: 1231006505,
+            },
+        );
+        vec![utxo1, utxo2, utxo3]
+    }
+
+    fn generate_random_utxos(rng: &mut StdRng, utxos_number: usize) -> Vec<WeightedUtxo> {
+        let mut res = Vec::new();
+        for i in 0..utxos_number {
+            res.push(WeightedUtxo {
+                satisfaction_weight: P2WPKH_SATISFACTION_SIZE,
+                utxo: Utxo::Local(LocalOutput {
+                    outpoint: OutPoint::from_str(&format!(
+                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:{}",
+                        i
+                    ))
+                    .unwrap(),
+                    txout: TxOut {
+                        value: Amount::from_sat(rng.gen_range(0..200000000)),
+                        script_pubkey: ScriptBuf::new(),
+                    },
+                    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 { last_seen: 0 }
+                    },
+                }),
+            });
+        }
+        res
+    }
+
+    fn generate_same_value_utxos(utxos_value: u64, utxos_number: usize) -> Vec<WeightedUtxo> {
+        (0..utxos_number)
+            .map(|i| WeightedUtxo {
+                satisfaction_weight: P2WPKH_SATISFACTION_SIZE,
+                utxo: Utxo::Local(LocalOutput {
+                    outpoint: OutPoint::from_str(&format!(
+                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:{}",
+                        i
+                    ))
+                    .unwrap(),
+                    txout: TxOut {
+                        value: Amount::from_sat(utxos_value),
+                        script_pubkey: ScriptBuf::new(),
+                    },
+                    keychain: KeychainKind::External,
+                    is_spent: false,
+                    derivation_index: 42,
+                    confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 },
+                }),
+            })
+            .collect()
+    }
+
+    fn sum_random_utxos(mut rng: &mut StdRng, utxos: &mut Vec<WeightedUtxo>) -> u64 {
+        let utxos_picked_len = rng.gen_range(2..utxos.len() / 2);
+        utxos.shuffle(&mut rng);
+        utxos[..utxos_picked_len]
+            .iter()
+            .map(|u| u.utxo.txout().value.to_sat())
+            .sum()
+    }
+
+    #[test]
+    fn test_largest_first_coin_selection_success() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 250_000 + FEE_AMOUNT;
+
+        let result = LargestFirstCoinSelection
+            .coin_select(
+                utxos,
+                vec![],
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300_010);
+        assert_eq!(result.fee_amount, 204)
+    }
+
+    #[test]
+    fn test_largest_first_coin_selection_use_all() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 20_000 + FEE_AMOUNT;
+
+        let result = LargestFirstCoinSelection
+            .coin_select(
+                utxos,
+                vec![],
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300_010);
+        assert_eq!(result.fee_amount, 204);
+    }
+
+    #[test]
+    fn test_largest_first_coin_selection_use_only_necessary() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 20_000 + FEE_AMOUNT;
+
+        let result = LargestFirstCoinSelection
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 1);
+        assert_eq!(result.selected_amount(), 200_000);
+        assert_eq!(result.fee_amount, 68);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_largest_first_coin_selection_insufficient_funds() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 500_000 + FEE_AMOUNT;
+
+        LargestFirstCoinSelection
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_largest_first_coin_selection_insufficient_funds_high_fees() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 250_000 + FEE_AMOUNT;
+
+        LargestFirstCoinSelection
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1000),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_oldest_first_coin_selection_success() {
+        let utxos = get_oldest_first_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 180_000 + FEE_AMOUNT;
+
+        let result = OldestFirstCoinSelection
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                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 utxos = get_oldest_first_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 20_000 + FEE_AMOUNT;
+
+        let result = OldestFirstCoinSelection
+            .coin_select(
+                utxos,
+                vec![],
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 500_000);
+        assert_eq!(result.fee_amount, 204);
+    }
+
+    #[test]
+    fn test_oldest_first_coin_selection_use_only_necessary() {
+        let utxos = get_oldest_first_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 20_000 + FEE_AMOUNT;
+
+        let result = OldestFirstCoinSelection
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 1);
+        assert_eq!(result.selected_amount(), 120_000);
+        assert_eq!(result.fee_amount, 68);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_oldest_first_coin_selection_insufficient_funds() {
+        let utxos = get_oldest_first_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 600_000 + FEE_AMOUNT;
+
+        OldestFirstCoinSelection
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_oldest_first_coin_selection_insufficient_funds_high_fees() {
+        let utxos = get_oldest_first_test_utxos();
+
+        let target_amount: u64 = utxos
+            .iter()
+            .map(|wu| wu.utxo.txout().value.to_sat())
+            .sum::<u64>()
+            - 50;
+        let drain_script = ScriptBuf::default();
+
+        OldestFirstCoinSelection
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1000),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_success() {
+        // In this case bnb won't find a suitable match and single random draw will
+        // select three outputs
+        let utxos = generate_same_value_utxos(100_000, 20);
+
+        let drain_script = ScriptBuf::default();
+
+        let target_amount = 250_000 + FEE_AMOUNT;
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300_000);
+        assert_eq!(result.fee_amount, 204);
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_required_are_enough() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 20_000 + FEE_AMOUNT;
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                utxos.clone(),
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300_010);
+        assert_eq!(result.fee_amount, 204);
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_optional_are_enough() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 299756 + FEE_AMOUNT;
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 2);
+        assert_eq!(result.selected_amount(), 300000);
+        assert_eq!(result.fee_amount, 136);
+    }
+
+    #[test]
+    #[ignore]
+    fn test_bnb_coin_selection_required_not_enough() {
+        let utxos = get_test_utxos();
+
+        let required = vec![utxos[0].clone()];
+        let mut optional = utxos[1..].to_vec();
+        optional.push(utxo(
+            500_000,
+            3,
+            ConfirmationTime::Unconfirmed { last_seen: 0 },
+        ));
+
+        // Defensive assertions, for sanity and in case someone changes the test utxos vector.
+        let amount: u64 = required.iter().map(|u| u.utxo.txout().value.to_sat()).sum();
+        assert_eq!(amount, 100_000);
+        let amount: u64 = optional.iter().map(|u| u.utxo.txout().value.to_sat()).sum();
+        assert!(amount > 150_000);
+        let drain_script = ScriptBuf::default();
+
+        let target_amount = 150_000 + FEE_AMOUNT;
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                required,
+                optional,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 2);
+        assert_eq!(result.selected_amount(), 300_000);
+        assert_eq!(result.fee_amount, 136);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bnb_coin_selection_insufficient_funds() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 500_000 + FEE_AMOUNT;
+
+        BranchAndBoundCoinSelection::default()
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bnb_coin_selection_insufficient_funds_high_fees() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 250_000 + FEE_AMOUNT;
+
+        BranchAndBoundCoinSelection::default()
+            .coin_select(
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb_unchecked(1000),
+                target_amount,
+                &drain_script,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_check_fee_rate() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+        let target_amount = 99932; // first utxo's effective value
+        let feerate = FeeRate::BROADCAST_MIN;
+
+        let result = BranchAndBoundCoinSelection::new(0)
+            .coin_select(vec![], utxos, feerate, target_amount, &drain_script)
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 1);
+        assert_eq!(result.selected_amount(), 100_000);
+        let input_weight =
+            TxIn::default().segwit_weight().to_wu() + P2WPKH_SATISFACTION_SIZE as u64;
+        // the final fee rate should be exactly the same as the fee rate given
+        let result_feerate = Amount::from_sat(result.fee_amount) / Weight::from_wu(input_weight);
+        assert_eq!(result_feerate, feerate);
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_exact_match() {
+        let seed = [0; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+
+        for _i in 0..200 {
+            let mut optional_utxos = generate_random_utxos(&mut rng, 16);
+            let target_amount = sum_random_utxos(&mut rng, &mut optional_utxos);
+            let drain_script = ScriptBuf::default();
+            let result = BranchAndBoundCoinSelection::new(0)
+                .coin_select(
+                    vec![],
+                    optional_utxos,
+                    FeeRate::ZERO,
+                    target_amount,
+                    &drain_script,
+                )
+                .unwrap();
+            assert_eq!(result.selected_amount(), target_amount);
+        }
+    }
+
+    #[test]
+    #[should_panic(expected = "BnBNoExactMatch")]
+    fn test_bnb_function_no_exact_match() {
+        let fee_rate = FeeRate::from_sat_per_vb_unchecked(10);
+        let utxos: Vec<OutputGroup> = get_test_utxos()
+            .into_iter()
+            .map(|u| OutputGroup::new(u, fee_rate))
+            .collect();
+
+        let curr_available_value = utxos.iter().fold(0, |acc, x| acc + x.effective_value);
+
+        let size_of_change = 31;
+        let cost_of_change = (Weight::from_vb_unchecked(size_of_change) * fee_rate).to_sat();
+
+        let drain_script = ScriptBuf::default();
+        let target_amount = 20_000 + FEE_AMOUNT;
+        BranchAndBoundCoinSelection::new(size_of_change)
+            .bnb(
+                vec![],
+                utxos,
+                0,
+                curr_available_value,
+                target_amount as i64,
+                cost_of_change,
+                &drain_script,
+                fee_rate,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "BnBTotalTriesExceeded")]
+    fn test_bnb_function_tries_exceeded() {
+        let fee_rate = FeeRate::from_sat_per_vb_unchecked(10);
+        let utxos: Vec<OutputGroup> = generate_same_value_utxos(100_000, 100_000)
+            .into_iter()
+            .map(|u| OutputGroup::new(u, fee_rate))
+            .collect();
+
+        let curr_available_value = utxos.iter().fold(0, |acc, x| acc + x.effective_value);
+
+        let size_of_change = 31;
+        let cost_of_change = (Weight::from_vb_unchecked(size_of_change) * fee_rate).to_sat();
+        let target_amount = 20_000 + FEE_AMOUNT;
+
+        let drain_script = ScriptBuf::default();
+
+        BranchAndBoundCoinSelection::new(size_of_change)
+            .bnb(
+                vec![],
+                utxos,
+                0,
+                curr_available_value,
+                target_amount as i64,
+                cost_of_change,
+                &drain_script,
+                fee_rate,
+            )
+            .unwrap();
+    }
+
+    // The match won't be exact but still in the range
+    #[test]
+    fn test_bnb_function_almost_exact_match_with_fees() {
+        let fee_rate = FeeRate::from_sat_per_vb_unchecked(1);
+        let size_of_change = 31;
+        let cost_of_change = (Weight::from_vb_unchecked(size_of_change) * fee_rate).to_sat();
+
+        let utxos: Vec<_> = generate_same_value_utxos(50_000, 10)
+            .into_iter()
+            .map(|u| OutputGroup::new(u, fee_rate))
+            .collect();
+
+        let curr_value = 0;
+
+        let curr_available_value = utxos.iter().fold(0, |acc, x| acc + x.effective_value);
+
+        // 2*(value of 1 utxo)  - 2*(1 utxo fees with 1.0sat/vbyte fee rate) -
+        // cost_of_change + 5.
+        let target_amount = 2 * 50_000 - 2 * 67 - cost_of_change as i64 + 5;
+
+        let drain_script = ScriptBuf::default();
+
+        let result = BranchAndBoundCoinSelection::new(size_of_change)
+            .bnb(
+                vec![],
+                utxos,
+                curr_value,
+                curr_available_value,
+                target_amount,
+                cost_of_change,
+                &drain_script,
+                fee_rate,
+            )
+            .unwrap();
+        assert_eq!(result.selected_amount(), 100_000);
+        assert_eq!(result.fee_amount, 136);
+    }
+
+    // TODO: bnb() function should be optimized, and this test should be done with more utxos
+    #[test]
+    fn test_bnb_function_exact_match_more_utxos() {
+        let seed = [0; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+        let fee_rate = FeeRate::ZERO;
+
+        for _ in 0..200 {
+            let optional_utxos: Vec<_> = generate_random_utxos(&mut rng, 40)
+                .into_iter()
+                .map(|u| OutputGroup::new(u, fee_rate))
+                .collect();
+
+            let curr_value = 0;
+
+            let curr_available_value = optional_utxos
+                .iter()
+                .fold(0, |acc, x| acc + x.effective_value);
+
+            let target_amount =
+                optional_utxos[3].effective_value + optional_utxos[23].effective_value;
+
+            let drain_script = ScriptBuf::default();
+
+            let result = BranchAndBoundCoinSelection::new(0)
+                .bnb(
+                    vec![],
+                    optional_utxos,
+                    curr_value,
+                    curr_available_value,
+                    target_amount,
+                    0,
+                    &drain_script,
+                    fee_rate,
+                )
+                .unwrap();
+            assert_eq!(result.selected_amount(), target_amount as u64);
+        }
+    }
+
+    #[test]
+    fn test_single_random_draw_function_success() {
+        let seed = [0; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+        let mut utxos = generate_random_utxos(&mut rng, 300);
+        let target_amount = sum_random_utxos(&mut rng, &mut utxos) + FEE_AMOUNT;
+
+        let fee_rate = FeeRate::from_sat_per_vb_unchecked(1);
+        let utxos: Vec<OutputGroup> = utxos
+            .into_iter()
+            .map(|u| OutputGroup::new(u, fee_rate))
+            .collect();
+
+        let drain_script = ScriptBuf::default();
+
+        let result = BranchAndBoundCoinSelection::default().single_random_draw(
+            vec![],
+            utxos,
+            0,
+            target_amount as i64,
+            &drain_script,
+            fee_rate,
+        );
+
+        assert!(result.selected_amount() > target_amount);
+        assert_eq!(result.fee_amount, (result.selected.len() * 68) as u64);
+    }
+
+    #[test]
+    fn test_bnb_exclude_negative_effective_value() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+
+        let selection = BranchAndBoundCoinSelection::default().coin_select(
+            vec![],
+            utxos,
+            FeeRate::from_sat_per_vb_unchecked(10),
+            500_000,
+            &drain_script,
+        );
+
+        assert_matches!(
+            selection,
+            Err(Error::InsufficientFunds {
+                available: 300_000,
+                ..
+            })
+        );
+    }
+
+    #[test]
+    fn test_bnb_include_negative_effective_value_when_required() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+
+        let (required, optional) = utxos.into_iter().partition(
+            |u| matches!(u, WeightedUtxo { utxo, .. } if utxo.txout().value.to_sat() < 1000),
+        );
+
+        let selection = BranchAndBoundCoinSelection::default().coin_select(
+            required,
+            optional,
+            FeeRate::from_sat_per_vb_unchecked(10),
+            500_000,
+            &drain_script,
+        );
+
+        assert_matches!(
+            selection,
+            Err(Error::InsufficientFunds {
+                available: 300_010,
+                ..
+            })
+        );
+    }
+
+    #[test]
+    fn test_bnb_sum_of_effective_value_negative() {
+        let utxos = get_test_utxos();
+        let drain_script = ScriptBuf::default();
+
+        let selection = BranchAndBoundCoinSelection::default().coin_select(
+            utxos,
+            vec![],
+            FeeRate::from_sat_per_vb_unchecked(10_000),
+            500_000,
+            &drain_script,
+        );
+
+        assert_matches!(
+            selection,
+            Err(Error::InsufficientFunds {
+                available: 300_010,
+                ..
+            })
+        );
+    }
+
+    #[test]
+    fn test_filter_duplicates() {
+        fn utxo(txid: &str, value: u64) -> WeightedUtxo {
+            WeightedUtxo {
+                satisfaction_weight: 0,
+                utxo: Utxo::Local(LocalOutput {
+                    outpoint: OutPoint::new(bitcoin::hashes::Hash::hash(txid.as_bytes()), 0),
+                    txout: TxOut {
+                        value: Amount::from_sat(value),
+                        script_pubkey: ScriptBuf::new(),
+                    },
+                    keychain: KeychainKind::External,
+                    is_spent: false,
+                    derivation_index: 0,
+                    confirmation_time: ConfirmationTime::Confirmed {
+                        height: 12345,
+                        time: 12345,
+                    },
+                }),
+            }
+        }
+
+        fn to_utxo_vec(utxos: &[(&str, u64)]) -> Vec<WeightedUtxo> {
+            let mut v = utxos
+                .iter()
+                .map(|&(txid, value)| utxo(txid, value))
+                .collect::<Vec<_>>();
+            v.sort_by_key(|u| u.utxo.outpoint());
+            v
+        }
+
+        struct TestCase<'a> {
+            name: &'a str,
+            required: &'a [(&'a str, u64)],
+            optional: &'a [(&'a str, u64)],
+            exp_required: &'a [(&'a str, u64)],
+            exp_optional: &'a [(&'a str, u64)],
+        }
+
+        let test_cases = [
+            TestCase {
+                name: "no_duplicates",
+                required: &[("A", 1000), ("B", 2100)],
+                optional: &[("C", 1000)],
+                exp_required: &[("A", 1000), ("B", 2100)],
+                exp_optional: &[("C", 1000)],
+            },
+            TestCase {
+                name: "duplicate_required_utxos",
+                required: &[("A", 3000), ("B", 1200), ("C", 1234), ("A", 3000)],
+                optional: &[("D", 2100)],
+                exp_required: &[("A", 3000), ("B", 1200), ("C", 1234)],
+                exp_optional: &[("D", 2100)],
+            },
+            TestCase {
+                name: "duplicate_optional_utxos",
+                required: &[("A", 3000), ("B", 1200)],
+                optional: &[("C", 5000), ("D", 1300), ("C", 5000)],
+                exp_required: &[("A", 3000), ("B", 1200)],
+                exp_optional: &[("C", 5000), ("D", 1300)],
+            },
+            TestCase {
+                name: "duplicate_across_required_and_optional_utxos",
+                required: &[("A", 3000), ("B", 1200), ("C", 2100)],
+                optional: &[("A", 3000), ("D", 1200), ("E", 5000)],
+                exp_required: &[("A", 3000), ("B", 1200), ("C", 2100)],
+                exp_optional: &[("D", 1200), ("E", 5000)],
+            },
+        ];
+
+        for (i, t) in test_cases.into_iter().enumerate() {
+            println!("Case {}: {}", i, t.name);
+            let (required, optional) =
+                filter_duplicates(to_utxo_vec(t.required), to_utxo_vec(t.optional));
+            assert_eq!(
+                required,
+                to_utxo_vec(t.exp_required),
+                "[{}:{}] unexpected `required` result",
+                i,
+                t.name
+            );
+            assert_eq!(
+                optional,
+                to_utxo_vec(t.exp_optional),
+                "[{}:{}] unexpected `optional` result",
+                i,
+                t.name
+            );
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/error.rs.html new file mode 100644 index 0000000000..7aa30fc5f8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/error.rs.html @@ -0,0 +1,585 @@ +error.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
+
// 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.
+
+//! Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
+
+use crate::descriptor::policy::PolicyError;
+use crate::descriptor::DescriptorError;
+use crate::wallet::coin_selection;
+use crate::{descriptor, KeychainKind};
+use alloc::string::String;
+use bitcoin::{absolute, psbt, OutPoint, Sequence, Txid};
+use core::fmt;
+
+/// Errors returned by miniscript when updating inconsistent PSBTs
+#[derive(Debug, Clone)]
+pub enum MiniscriptPsbtError {
+    /// Descriptor key conversion error
+    Conversion(miniscript::descriptor::ConversionError),
+    /// Return error type for PsbtExt::update_input_with_descriptor
+    UtxoUpdate(miniscript::psbt::UtxoUpdateError),
+    /// Return error type for PsbtExt::update_output_with_descriptor
+    OutputUpdate(miniscript::psbt::OutputUpdateError),
+}
+
+impl fmt::Display for MiniscriptPsbtError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Conversion(err) => write!(f, "Conversion error: {}", err),
+            Self::UtxoUpdate(err) => write!(f, "UTXO update error: {}", err),
+            Self::OutputUpdate(err) => write!(f, "Output update error: {}", err),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for MiniscriptPsbtError {}
+
+#[derive(Debug)]
+/// Error returned from [`TxBuilder::finish`]
+///
+/// [`TxBuilder::finish`]: crate::wallet::tx_builder::TxBuilder::finish
+pub enum CreateTxError {
+    /// There was a problem with the descriptors passed in
+    Descriptor(DescriptorError),
+    /// We were unable to load wallet data from or write wallet data to the persistence backend
+    Persist(anyhow::Error),
+    /// There was a problem while extracting and manipulating policies
+    Policy(PolicyError),
+    /// Spending policy is not compatible with this [`KeychainKind`]
+    SpendingPolicyRequired(KeychainKind),
+    /// Requested invalid transaction version '0'
+    Version0,
+    /// Requested transaction version `1`, but at least `2` is needed to use OP_CSV
+    Version1Csv,
+    /// Requested `LockTime` is less than is required to spend from this script
+    LockTime {
+        /// Requested `LockTime`
+        requested: absolute::LockTime,
+        /// Required `LockTime`
+        required: absolute::LockTime,
+    },
+    /// Cannot enable RBF with a `Sequence` >= 0xFFFFFFFE
+    RbfSequence,
+    /// Cannot enable RBF with `Sequence` given a required OP_CSV
+    RbfSequenceCsv {
+        /// Given RBF `Sequence`
+        rbf: Sequence,
+        /// Required OP_CSV `Sequence`
+        csv: Sequence,
+    },
+    /// When bumping a tx the absolute fee requested is lower than replaced tx absolute fee
+    FeeTooLow {
+        /// Required fee absolute value (satoshi)
+        required: u64,
+    },
+    /// When bumping a tx the fee rate requested is lower than required
+    FeeRateTooLow {
+        /// Required fee rate
+        required: bitcoin::FeeRate,
+    },
+    /// `manually_selected_only` option is selected but no utxo has been passed
+    NoUtxosSelected,
+    /// Output created is under the dust limit, 546 satoshis
+    OutputBelowDustLimit(usize),
+    /// The `change_policy` was set but the wallet does not have a change_descriptor
+    ChangePolicyDescriptor,
+    /// There was an error with coin selection
+    CoinSelection(coin_selection::Error),
+    /// Wallet's UTXO set is not enough to cover recipient's requested plus fee
+    InsufficientFunds {
+        /// Sats needed for some transaction
+        needed: u64,
+        /// Sats available for spending
+        available: u64,
+    },
+    /// Cannot build a tx without recipients
+    NoRecipients,
+    /// Partially signed bitcoin transaction error
+    Psbt(psbt::Error),
+    /// In order to use the [`TxBuilder::add_global_xpubs`] option every extended
+    /// key in the descriptor must either be a master key itself (having depth = 0) or have an
+    /// explicit origin provided
+    ///
+    /// [`TxBuilder::add_global_xpubs`]: crate::wallet::tx_builder::TxBuilder::add_global_xpubs
+    MissingKeyOrigin(String),
+    /// Happens when trying to spend an UTXO that is not in the internal database
+    UnknownUtxo,
+    /// Missing non_witness_utxo on foreign utxo for given `OutPoint`
+    MissingNonWitnessUtxo(OutPoint),
+    /// Miniscript PSBT error
+    MiniscriptPsbt(MiniscriptPsbtError),
+}
+
+impl fmt::Display for CreateTxError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Descriptor(e) => e.fmt(f),
+            Self::Persist(e) => {
+                write!(
+                    f,
+                    "failed to load wallet data from or write wallet data to persistence backend: {}",
+                    e
+                )
+            }
+            Self::Policy(e) => e.fmt(f),
+            CreateTxError::SpendingPolicyRequired(keychain_kind) => {
+                write!(f, "Spending policy required: {:?}", keychain_kind)
+            }
+            CreateTxError::Version0 => {
+                write!(f, "Invalid version `0`")
+            }
+            CreateTxError::Version1Csv => {
+                write!(
+                    f,
+                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
+                )
+            }
+            CreateTxError::LockTime {
+                requested,
+                required,
+            } => {
+                write!(f, "TxBuilder requested timelock of `{:?}`, but at least `{:?}` is required to spend from this script", required, requested)
+            }
+            CreateTxError::RbfSequence => {
+                write!(f, "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")
+            }
+            CreateTxError::RbfSequenceCsv { rbf, csv } => {
+                write!(
+                    f,
+                    "Cannot enable RBF with nSequence `{:?}` given a required OP_CSV of `{:?}`",
+                    rbf, csv
+                )
+            }
+            CreateTxError::FeeTooLow { required } => {
+                write!(f, "Fee to low: required {} sat", required)
+            }
+            CreateTxError::FeeRateTooLow { required } => {
+                write!(
+                    f,
+                    // Note: alternate fmt as sat/vb (ceil) available in bitcoin-0.31
+                    //"Fee rate too low: required {required:#}"
+                    "Fee rate too low: required {} sat/vb",
+                    crate::floating_rate!(required)
+                )
+            }
+            CreateTxError::NoUtxosSelected => {
+                write!(f, "No UTXO selected")
+            }
+            CreateTxError::OutputBelowDustLimit(limit) => {
+                write!(f, "Output below the dust limit: {}", limit)
+            }
+            CreateTxError::ChangePolicyDescriptor => {
+                write!(
+                    f,
+                    "The `change_policy` can be set only if the wallet has a change_descriptor"
+                )
+            }
+            CreateTxError::CoinSelection(e) => e.fmt(f),
+            CreateTxError::InsufficientFunds { needed, available } => {
+                write!(
+                    f,
+                    "Insufficient funds: {} sat available of {} sat needed",
+                    available, needed
+                )
+            }
+            CreateTxError::NoRecipients => {
+                write!(f, "Cannot build tx without recipients")
+            }
+            CreateTxError::Psbt(e) => e.fmt(f),
+            CreateTxError::MissingKeyOrigin(err) => {
+                write!(f, "Missing key origin: {}", err)
+            }
+            CreateTxError::UnknownUtxo => {
+                write!(f, "UTXO not found in the internal database")
+            }
+            CreateTxError::MissingNonWitnessUtxo(outpoint) => {
+                write!(f, "Missing non_witness_utxo on foreign utxo {}", outpoint)
+            }
+            CreateTxError::MiniscriptPsbt(err) => {
+                write!(f, "Miniscript PSBT error: {}", err)
+            }
+        }
+    }
+}
+
+impl From<descriptor::error::Error> for CreateTxError {
+    fn from(err: descriptor::error::Error) -> Self {
+        CreateTxError::Descriptor(err)
+    }
+}
+
+impl From<PolicyError> for CreateTxError {
+    fn from(err: PolicyError) -> Self {
+        CreateTxError::Policy(err)
+    }
+}
+
+impl From<MiniscriptPsbtError> for CreateTxError {
+    fn from(err: MiniscriptPsbtError) -> Self {
+        CreateTxError::MiniscriptPsbt(err)
+    }
+}
+
+impl From<psbt::Error> for CreateTxError {
+    fn from(err: psbt::Error) -> Self {
+        CreateTxError::Psbt(err)
+    }
+}
+
+impl From<coin_selection::Error> for CreateTxError {
+    fn from(err: coin_selection::Error) -> Self {
+        CreateTxError::CoinSelection(err)
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for CreateTxError {}
+
+#[derive(Debug)]
+/// Error returned from [`Wallet::build_fee_bump`]
+///
+/// [`Wallet::build_fee_bump`]: super::Wallet::build_fee_bump
+pub enum BuildFeeBumpError {
+    /// Happens when trying to spend an UTXO that is not in the internal database
+    UnknownUtxo(OutPoint),
+    /// Thrown when a tx is not found in the internal database
+    TransactionNotFound(Txid),
+    /// Happens when trying to bump a transaction that is already confirmed
+    TransactionConfirmed(Txid),
+    /// Trying to replace a tx that has a sequence >= `0xFFFFFFFE`
+    IrreplaceableTransaction(Txid),
+    /// Node doesn't have data to estimate a fee rate
+    FeeRateUnavailable,
+}
+
+impl fmt::Display for BuildFeeBumpError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::UnknownUtxo(outpoint) => write!(
+                f,
+                "UTXO not found in the internal database with txid: {}, vout: {}",
+                outpoint.txid, outpoint.vout
+            ),
+            Self::TransactionNotFound(txid) => {
+                write!(
+                    f,
+                    "Transaction not found in the internal database with txid: {}",
+                    txid
+                )
+            }
+            Self::TransactionConfirmed(txid) => {
+                write!(f, "Transaction already confirmed with txid: {}", txid)
+            }
+            Self::IrreplaceableTransaction(txid) => {
+                write!(f, "Transaction can't be replaced with txid: {}", txid)
+            }
+            Self::FeeRateUnavailable => write!(f, "Fee rate unavailable"),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for BuildFeeBumpError {}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/export.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/export.rs.html new file mode 100644 index 0000000000..769d87c3e8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/export.rs.html @@ -0,0 +1,685 @@ +export.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
+
// 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.
+
+//! Wallet export
+//!
+//! This modules implements the wallet export format used by [FullyNoded](https://github.com/Fonta1n3/FullyNoded/blob/10b7808c8b929b171cca537fb50522d015168ac9/Docs/Wallets/Wallet-Export-Spec.md).
+//!
+//! ## Examples
+//!
+//! ### Import from JSON
+//!
+//! ```
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bdk_wallet::wallet::export::*;
+//! # use bdk_wallet::*;
+//! let import = r#"{
+//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
+//!     "blockheight":1782088,
+//!     "label":"testnet"
+//! }"#;
+//!
+//! let import = FullyNodedExport::from_str(import)?;
+//! let wallet = Wallet::new_no_persist(
+//!     &import.descriptor(),
+//!     import.change_descriptor().as_ref(),
+//!     Network::Testnet,
+//! )?;
+//! # Ok::<_, Box<dyn std::error::Error>>(())
+//! ```
+//!
+//! ### Export a `Wallet`
+//! ```
+//! # use bitcoin::*;
+//! # use bdk_wallet::wallet::export::*;
+//! # use bdk_wallet::*;
+//! let wallet = Wallet::new_no_persist(
+//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+//!     Network::Testnet,
+//! )?;
+//! let export = FullyNodedExport::export_wallet(&wallet, "exported wallet", true).unwrap();
+//!
+//! println!("Exported: {}", export.to_string());
+//! # Ok::<_, Box<dyn std::error::Error>>(())
+//! ```
+
+use alloc::string::String;
+use core::fmt;
+use core::str::FromStr;
+use serde::{Deserialize, Serialize};
+
+use miniscript::descriptor::{ShInner, WshInner};
+use miniscript::{Descriptor, ScriptContext, Terminal};
+
+use crate::types::KeychainKind;
+use crate::wallet::Wallet;
+
+/// Alias for [`FullyNodedExport`]
+#[deprecated(since = "0.18.0", note = "Please use [`FullyNodedExport`] instead")]
+pub type WalletExport = FullyNodedExport;
+
+/// Structure that contains the export of a wallet
+///
+/// For a usage example see [this module](crate::wallet::export)'s documentation.
+#[derive(Debug, Serialize, Deserialize)]
+pub struct FullyNodedExport {
+    descriptor: String,
+    /// Earliest block to rescan when looking for the wallet's transactions
+    pub blockheight: u32,
+    /// Arbitrary label for the wallet
+    pub label: String,
+}
+
+impl fmt::Display for FullyNodedExport {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", serde_json::to_string(self).unwrap())
+    }
+}
+
+impl FromStr for FullyNodedExport {
+    type Err = serde_json::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        serde_json::from_str(s)
+    }
+}
+
+fn remove_checksum(s: String) -> String {
+    s.split_once('#').map(|(a, _)| String::from(a)).unwrap()
+}
+
+impl FullyNodedExport {
+    /// 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.
+    ///
+    /// If `include_blockheight` is `true`, this function will look into the `wallet`'s database
+    /// 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`.
+    pub fn export_wallet(
+        wallet: &Wallet,
+        label: &str,
+        include_blockheight: bool,
+    ) -> Result<Self, &'static str> {
+        let descriptor = wallet
+            .get_descriptor_for_keychain(KeychainKind::External)
+            .to_string_with_secret(
+                &wallet
+                    .get_signers(KeychainKind::External)
+                    .as_key_map(wallet.secp_ctx()),
+            );
+        let descriptor = remove_checksum(descriptor);
+        Self::is_compatible_with_core(&descriptor)?;
+
+        let blockheight = if include_blockheight {
+            wallet.transactions().next().map_or(0, |canonical_tx| {
+                match canonical_tx.chain_position {
+                    bdk_chain::ChainPosition::Confirmed(a) => a.confirmation_height,
+                    bdk_chain::ChainPosition::Unconfirmed(_) => 0,
+                }
+            })
+        } else {
+            0
+        };
+
+        let export = FullyNodedExport {
+            descriptor,
+            label: label.into(),
+            blockheight,
+        };
+
+        let change_descriptor = match wallet.public_descriptor(KeychainKind::Internal).is_some() {
+            false => None,
+            true => {
+                let descriptor = wallet
+                    .get_descriptor_for_keychain(KeychainKind::Internal)
+                    .to_string_with_secret(
+                        &wallet
+                            .get_signers(KeychainKind::Internal)
+                            .as_key_map(wallet.secp_ctx()),
+                    );
+                Some(remove_checksum(descriptor))
+            }
+        };
+        if export.change_descriptor() != change_descriptor {
+            return Err("Incompatible change descriptor");
+        }
+
+        Ok(export)
+    }
+
+    fn is_compatible_with_core(descriptor: &str) -> Result<(), &'static str> {
+        fn check_ms<Ctx: ScriptContext>(
+            terminal: &Terminal<String, Ctx>,
+        ) -> Result<(), &'static str> {
+            if let Terminal::Multi(_, _) = terminal {
+                Ok(())
+            } else {
+                Err("The descriptor contains operators not supported by Bitcoin Core")
+            }
+        }
+
+        // pkh(), wpkh(), sh(wpkh()) are always fine, as well as multi() and sortedmulti()
+        match Descriptor::<String>::from_str(descriptor).map_err(|_| "Invalid descriptor")? {
+            Descriptor::Pkh(_) | Descriptor::Wpkh(_) => Ok(()),
+            Descriptor::Sh(sh) => match sh.as_inner() {
+                ShInner::Wpkh(_) => Ok(()),
+                ShInner::SortedMulti(_) => Ok(()),
+                ShInner::Wsh(wsh) => match wsh.as_inner() {
+                    WshInner::SortedMulti(_) => Ok(()),
+                    WshInner::Ms(ms) => check_ms(&ms.node),
+                },
+                ShInner::Ms(ms) => check_ms(&ms.node),
+            },
+            Descriptor::Wsh(wsh) => match wsh.as_inner() {
+                WshInner::SortedMulti(_) => Ok(()),
+                WshInner::Ms(ms) => check_ms(&ms.node),
+            },
+            _ => Err("The descriptor is not compatible with Bitcoin Core"),
+        }
+    }
+
+    /// Return the external descriptor
+    pub fn descriptor(&self) -> String {
+        self.descriptor.clone()
+    }
+
+    /// Return the internal descriptor, if present
+    pub fn change_descriptor(&self) -> Option<String> {
+        let replaced = self.descriptor.replace("/0/*", "/1/*");
+
+        if replaced != self.descriptor {
+            Some(replaced)
+        } else {
+            None
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use core::str::FromStr;
+
+    use crate::std::string::ToString;
+    use bdk_chain::{BlockId, ConfirmationTime};
+    use bitcoin::hashes::Hash;
+    use bitcoin::{transaction, BlockHash, Network, Transaction};
+
+    use super::*;
+    use crate::wallet::Wallet;
+
+    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: transaction::Version::non_standard(0),
+            lock_time: bitcoin::absolute::LockTime::ZERO,
+        };
+        wallet
+            .insert_checkpoint(BlockId {
+                height: 5001,
+                hash: BlockHash::all_zeros(),
+            })
+            .unwrap();
+        wallet
+            .insert_tx(
+                transaction,
+                ConfirmationTime::Confirmed {
+                    height: 5000,
+                    time: 0,
+                },
+            )
+            .unwrap();
+        wallet
+    }
+
+    #[test]
+    fn test_export_bip44() {
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
+
+        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);
+        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
+        assert_eq!(export.blockheight, 5000);
+        assert_eq!(export.label, "Test Label");
+    }
+
+    #[test]
+    #[should_panic(expected = "Incompatible change descriptor")]
+    fn test_export_no_change() {
+        // This wallet explicitly doesn't have a change descriptor. It should be impossible to
+        // export, because exporting this kind of external descriptor normally implies the
+        // existence of an internal descriptor
+
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+
+        let wallet = get_test_wallet(descriptor, None, Network::Bitcoin);
+        FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "Incompatible change descriptor")]
+    fn test_export_incompatible_change() {
+        // This wallet has a change descriptor, but the derivation path is not in the "standard"
+        // bip44/49/etc format
+
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/50'/0'/1/*)";
+
+        let wallet = get_test_wallet(descriptor, Some(change_descriptor), Network::Bitcoin);
+        FullyNodedExport::export_wallet(&wallet, "Test Label", true).unwrap();
+    }
+
+    #[test]
+    fn test_export_multi() {
+        let descriptor = "wsh(multi(2,\
+                                [73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*,\
+                                [f9f62194/48'/0'/0'/2']tpubDDp3ZSH1yCwusRppH7zgSxq2t1VEUyXSeEp8E5aFS8m43MknUjiF1bSLo3CGWAxbDyhF1XowA5ukPzyJZjznYk3kYi6oe7QxtX2euvKWsk4/0/*,\
+                                [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/0/*\
+                          ))";
+        let change_descriptor = "wsh(multi(2,\
+                                       [73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/1/*,\
+                                       [f9f62194/48'/0'/0'/2']tpubDDp3ZSH1yCwusRppH7zgSxq2t1VEUyXSeEp8E5aFS8m43MknUjiF1bSLo3CGWAxbDyhF1XowA5ukPzyJZjznYk3kYi6oe7QxtX2euvKWsk4/1/*,\
+                                       [c98b1535/48'/0'/0'/2']tpubDCDi5W4sP6zSnzJeowy8rQDVhBdRARaPhK1axABi8V1661wEPeanpEXj4ZLAUEoikVtoWcyK26TKKJSecSfeKxwHCcRrge9k1ybuiL71z4a/1/*\
+                                 ))";
+
+        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);
+        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
+        assert_eq!(export.blockheight, 5000);
+        assert_eq!(export.label, "Test Label");
+    }
+
+    #[test]
+    fn test_export_to_json() {
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
+
+        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\"}");
+    }
+
+    #[test]
+    fn test_export_from_json() {
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
+
+        let import_str = "{\"descriptor\":\"wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44\'/0\'/0\'/0/*)\",\"blockheight\":5000,\"label\":\"Test Label\"}";
+        let export = FullyNodedExport::from_str(import_str).unwrap();
+
+        assert_eq!(export.descriptor(), descriptor);
+        assert_eq!(export.change_descriptor(), Some(change_descriptor.into()));
+        assert_eq!(export.blockheight, 5000);
+        assert_eq!(export.label, "Test Label");
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/mod.rs.html new file mode 100644 index 0000000000..cc7eadab31 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/mod.rs.html @@ -0,0 +1,5419 @@ +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
+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
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+1194
+1195
+1196
+1197
+1198
+1199
+1200
+1201
+1202
+1203
+1204
+1205
+1206
+1207
+1208
+1209
+1210
+1211
+1212
+1213
+1214
+1215
+1216
+1217
+1218
+1219
+1220
+1221
+1222
+1223
+1224
+1225
+1226
+1227
+1228
+1229
+1230
+1231
+1232
+1233
+1234
+1235
+1236
+1237
+1238
+1239
+1240
+1241
+1242
+1243
+1244
+1245
+1246
+1247
+1248
+1249
+1250
+1251
+1252
+1253
+1254
+1255
+1256
+1257
+1258
+1259
+1260
+1261
+1262
+1263
+1264
+1265
+1266
+1267
+1268
+1269
+1270
+1271
+1272
+1273
+1274
+1275
+1276
+1277
+1278
+1279
+1280
+1281
+1282
+1283
+1284
+1285
+1286
+1287
+1288
+1289
+1290
+1291
+1292
+1293
+1294
+1295
+1296
+1297
+1298
+1299
+1300
+1301
+1302
+1303
+1304
+1305
+1306
+1307
+1308
+1309
+1310
+1311
+1312
+1313
+1314
+1315
+1316
+1317
+1318
+1319
+1320
+1321
+1322
+1323
+1324
+1325
+1326
+1327
+1328
+1329
+1330
+1331
+1332
+1333
+1334
+1335
+1336
+1337
+1338
+1339
+1340
+1341
+1342
+1343
+1344
+1345
+1346
+1347
+1348
+1349
+1350
+1351
+1352
+1353
+1354
+1355
+1356
+1357
+1358
+1359
+1360
+1361
+1362
+1363
+1364
+1365
+1366
+1367
+1368
+1369
+1370
+1371
+1372
+1373
+1374
+1375
+1376
+1377
+1378
+1379
+1380
+1381
+1382
+1383
+1384
+1385
+1386
+1387
+1388
+1389
+1390
+1391
+1392
+1393
+1394
+1395
+1396
+1397
+1398
+1399
+1400
+1401
+1402
+1403
+1404
+1405
+1406
+1407
+1408
+1409
+1410
+1411
+1412
+1413
+1414
+1415
+1416
+1417
+1418
+1419
+1420
+1421
+1422
+1423
+1424
+1425
+1426
+1427
+1428
+1429
+1430
+1431
+1432
+1433
+1434
+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
+1596
+1597
+1598
+1599
+1600
+1601
+1602
+1603
+1604
+1605
+1606
+1607
+1608
+1609
+1610
+1611
+1612
+1613
+1614
+1615
+1616
+1617
+1618
+1619
+1620
+1621
+1622
+1623
+1624
+1625
+1626
+1627
+1628
+1629
+1630
+1631
+1632
+1633
+1634
+1635
+1636
+1637
+1638
+1639
+1640
+1641
+1642
+1643
+1644
+1645
+1646
+1647
+1648
+1649
+1650
+1651
+1652
+1653
+1654
+1655
+1656
+1657
+1658
+1659
+1660
+1661
+1662
+1663
+1664
+1665
+1666
+1667
+1668
+1669
+1670
+1671
+1672
+1673
+1674
+1675
+1676
+1677
+1678
+1679
+1680
+1681
+1682
+1683
+1684
+1685
+1686
+1687
+1688
+1689
+1690
+1691
+1692
+1693
+1694
+1695
+1696
+1697
+1698
+1699
+1700
+1701
+1702
+1703
+1704
+1705
+1706
+1707
+1708
+1709
+1710
+1711
+1712
+1713
+1714
+1715
+1716
+1717
+1718
+1719
+1720
+1721
+1722
+1723
+1724
+1725
+1726
+1727
+1728
+1729
+1730
+1731
+1732
+1733
+1734
+1735
+1736
+1737
+1738
+1739
+1740
+1741
+1742
+1743
+1744
+1745
+1746
+1747
+1748
+1749
+1750
+1751
+1752
+1753
+1754
+1755
+1756
+1757
+1758
+1759
+1760
+1761
+1762
+1763
+1764
+1765
+1766
+1767
+1768
+1769
+1770
+1771
+1772
+1773
+1774
+1775
+1776
+1777
+1778
+1779
+1780
+1781
+1782
+1783
+1784
+1785
+1786
+1787
+1788
+1789
+1790
+1791
+1792
+1793
+1794
+1795
+1796
+1797
+1798
+1799
+1800
+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
+
// 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.
+
+//! Wallet
+//!
+//! This module defines the [`Wallet`].
+use crate::collections::{BTreeMap, HashMap};
+use alloc::{
+    boxed::Box,
+    string::{String, ToString},
+    sync::Arc,
+    vec::Vec,
+};
+pub use bdk_chain::keychain::Balance;
+use bdk_chain::{
+    indexed_tx_graph,
+    keychain::{self, KeychainTxOutIndex},
+    local_chain::{
+        self, ApplyHeaderError, CannotConnectError, CheckPoint, CheckPointIter, LocalChain,
+    },
+    spk_client::{FullScanRequest, FullScanResult, SyncRequest, SyncResult},
+    tx_graph::{CanonicalTx, TxGraph},
+    Append, BlockId, ChainPosition, ConfirmationTime, ConfirmationTimeHeightAnchor, FullTxOut,
+    IndexedTxGraph,
+};
+use bdk_persist::{Persist, PersistBackend};
+use bitcoin::secp256k1::{All, Secp256k1};
+use bitcoin::sighash::{EcdsaSighashType, TapSighashType};
+use bitcoin::{
+    absolute, psbt, Address, Block, FeeRate, Network, OutPoint, Script, ScriptBuf, Sequence,
+    Transaction, TxOut, Txid, Witness,
+};
+use bitcoin::{consensus::encode::serialize, transaction, BlockHash, Psbt};
+use bitcoin::{constants::genesis_block, Amount};
+use core::fmt;
+use core::ops::Deref;
+use descriptor::error::Error as DescriptorError;
+use miniscript::psbt::{PsbtExt, PsbtInputExt, PsbtInputSatisfier};
+
+use bdk_chain::tx_graph::CalculateFeeError;
+
+pub mod coin_selection;
+pub mod export;
+pub mod signer;
+pub mod tx_builder;
+pub(crate) mod utils;
+
+pub mod error;
+
+pub use utils::IsDust;
+
+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::descriptor::policy::BuildSatisfaction;
+use crate::descriptor::{
+    self, calc_checksum, into_wallet_descriptor_checked, DerivedDescriptor, DescriptorMeta,
+    ExtendedDescriptor, ExtractPolicy, IntoWalletDescriptor, Policy, XKeyUtils,
+};
+use crate::psbt::PsbtUtils;
+use crate::signer::SignerError;
+use crate::types::*;
+use crate::wallet::coin_selection::Excess::{Change, NoChange};
+use crate::wallet::error::{BuildFeeBumpError, CreateTxError, MiniscriptPsbtError};
+
+const COINBASE_MATURITY: u32 = 100;
+
+/// A Bitcoin wallet
+///
+/// The `Wallet` 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. [`signer`]s that can contribute signatures to addresses instantiated from the descriptors.
+///
+/// [`signer`]: crate::signer
+#[derive(Debug)]
+pub struct Wallet {
+    signers: Arc<SignersContainer>,
+    change_signers: Arc<SignersContainer>,
+    chain: LocalChain,
+    indexed_graph: IndexedTxGraph<ConfirmationTimeHeightAnchor, KeychainTxOutIndex<KeychainKind>>,
+    persist: Persist<ChangeSet>,
+    network: Network,
+    secp: SecpCtx,
+}
+
+/// An update to [`Wallet`].
+///
+/// It updates [`bdk_chain::keychain::KeychainTxOutIndex`], [`bdk_chain::TxGraph`] and [`local_chain::LocalChain`] atomically.
+#[derive(Debug, Clone, Default)]
+pub struct Update {
+    /// Contains the last active derivation indices per keychain (`K`), which is used to update the
+    /// [`KeychainTxOutIndex`].
+    pub last_active_indices: BTreeMap<KeychainKind, u32>,
+
+    /// Update for the wallet's internal [`TxGraph`].
+    pub graph: TxGraph<ConfirmationTimeHeightAnchor>,
+
+    /// Update for the wallet's internal [`LocalChain`].
+    ///
+    /// [`LocalChain`]: local_chain::LocalChain
+    pub chain: Option<CheckPoint>,
+}
+
+impl From<FullScanResult<KeychainKind>> for Update {
+    fn from(value: FullScanResult<KeychainKind>) -> Self {
+        Self {
+            last_active_indices: value.last_active_indices,
+            graph: value.graph_update,
+            chain: Some(value.chain_update),
+        }
+    }
+}
+
+impl From<SyncResult> for Update {
+    fn from(value: SyncResult) -> Self {
+        Self {
+            last_active_indices: BTreeMap::new(),
+            graph: value.graph_update,
+            chain: Some(value.chain_update),
+        }
+    }
+}
+
+/// The changes made to a wallet by applying an [`Update`].
+#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, Default)]
+pub struct ChangeSet {
+    /// Changes to the [`LocalChain`].
+    ///
+    /// [`LocalChain`]: local_chain::LocalChain
+    pub chain: local_chain::ChangeSet,
+
+    /// Changes to [`IndexedTxGraph`].
+    ///
+    /// [`IndexedTxGraph`]: bdk_chain::indexed_tx_graph::IndexedTxGraph
+    pub indexed_tx_graph: indexed_tx_graph::ChangeSet<
+        ConfirmationTimeHeightAnchor,
+        keychain::ChangeSet<KeychainKind>,
+    >,
+
+    /// Stores the network type of the wallet.
+    pub network: Option<Network>,
+}
+
+impl Append for ChangeSet {
+    fn append(&mut self, other: Self) {
+        Append::append(&mut self.chain, other.chain);
+        Append::append(&mut self.indexed_tx_graph, other.indexed_tx_graph);
+        if other.network.is_some() {
+            debug_assert!(
+                self.network.is_none() || self.network == other.network,
+                "network type must be consistent"
+            );
+            self.network = other.network;
+        }
+    }
+
+    fn is_empty(&self) -> bool {
+        self.chain.is_empty() && self.indexed_tx_graph.is_empty()
+    }
+}
+
+impl From<local_chain::ChangeSet> for ChangeSet {
+    fn from(chain: local_chain::ChangeSet) -> Self {
+        Self {
+            chain,
+            ..Default::default()
+        }
+    }
+}
+
+impl
+    From<
+        indexed_tx_graph::ChangeSet<
+            ConfirmationTimeHeightAnchor,
+            keychain::ChangeSet<KeychainKind>,
+        >,
+    > for ChangeSet
+{
+    fn from(
+        indexed_tx_graph: indexed_tx_graph::ChangeSet<
+            ConfirmationTimeHeightAnchor,
+            keychain::ChangeSet<KeychainKind>,
+        >,
+    ) -> Self {
+        Self {
+            indexed_tx_graph,
+            ..Default::default()
+        }
+    }
+}
+
+/// A derived address and the index it was found at.
+/// For convenience this automatically derefs to `Address`
+#[derive(Debug, PartialEq, Eq)]
+pub struct AddressInfo {
+    /// Child index of this address
+    pub index: u32,
+    /// Address
+    pub address: Address,
+    /// Type of keychain
+    pub keychain: KeychainKind,
+}
+
+impl Deref for AddressInfo {
+    type Target = Address;
+
+    fn deref(&self) -> &Self::Target {
+        &self.address
+    }
+}
+
+impl fmt::Display for AddressInfo {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.address)
+    }
+}
+
+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, DescriptorError> {
+        Self::new(descriptor, change_descriptor, (), network).map_err(|e| match e {
+            NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"),
+            NewError::Descriptor(e) => e,
+            NewError::Persist(_) => unreachable!("mock-write must always succeed"),
+        })
+    }
+
+    /// Creates a wallet that does not persist data, with a custom genesis hash.
+    pub fn new_no_persist_with_genesis_hash<E: IntoWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        network: Network,
+        genesis_hash: BlockHash,
+    ) -> Result<Self, crate::descriptor::DescriptorError> {
+        Self::new_with_genesis_hash(descriptor, change_descriptor, (), network, genesis_hash)
+            .map_err(|e| match e {
+                NewError::NonEmptyDatabase => unreachable!("mock-database cannot have data"),
+                NewError::Descriptor(e) => e,
+                NewError::Persist(_) => unreachable!("mock-write must always succeed"),
+            })
+    }
+}
+
+/// The error type when constructing a fresh [`Wallet`].
+///
+/// Methods [`new`] and [`new_with_genesis_hash`] may return this error.
+///
+/// [`new`]: Wallet::new
+/// [`new_with_genesis_hash`]: Wallet::new_with_genesis_hash
+#[derive(Debug)]
+pub enum NewError {
+    /// Database already has data.
+    NonEmptyDatabase,
+    /// There was problem with the passed-in descriptor(s).
+    Descriptor(crate::descriptor::DescriptorError),
+    /// We were unable to write the wallet's data to the persistence backend.
+    Persist(anyhow::Error),
+}
+
+impl fmt::Display for NewError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            NewError::NonEmptyDatabase => write!(
+                f,
+                "database already has data - use `load` or `new_or_load` methods instead"
+            ),
+            NewError::Descriptor(e) => e.fmt(f),
+            NewError::Persist(e) => e.fmt(f),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for NewError {}
+
+/// The error type when loading a [`Wallet`] from persistence.
+///
+/// Method [`load`] may return this error.
+///
+/// [`load`]: Wallet::load
+#[derive(Debug)]
+pub enum LoadError {
+    /// There was a problem with the passed-in descriptor(s).
+    Descriptor(crate::descriptor::DescriptorError),
+    /// Loading data from the persistence backend failed.
+    Persist(anyhow::Error),
+    /// Wallet not initialized, persistence backend is empty.
+    NotInitialized,
+    /// Data loaded from persistence is missing network type.
+    MissingNetwork,
+    /// Data loaded from persistence is missing genesis hash.
+    MissingGenesis,
+    /// Data loaded from persistence is missing descriptor.
+    MissingDescriptor,
+}
+
+impl fmt::Display for LoadError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            LoadError::Descriptor(e) => e.fmt(f),
+            LoadError::Persist(e) => e.fmt(f),
+            LoadError::NotInitialized => {
+                write!(f, "wallet is not initialized, persistence backend is empty")
+            }
+            LoadError::MissingNetwork => write!(f, "loaded data is missing network type"),
+            LoadError::MissingGenesis => write!(f, "loaded data is missing genesis hash"),
+            LoadError::MissingDescriptor => write!(f, "loaded data is missing descriptor"),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for LoadError {}
+
+/// Error type for when we try load a [`Wallet`] from persistence and creating it if non-existent.
+///
+/// Methods [`new_or_load`] and [`new_or_load_with_genesis_hash`] may return this error.
+///
+/// [`new_or_load`]: Wallet::new_or_load
+/// [`new_or_load_with_genesis_hash`]: Wallet::new_or_load_with_genesis_hash
+#[derive(Debug)]
+pub enum NewOrLoadError {
+    /// There is a problem with the passed-in descriptor.
+    Descriptor(crate::descriptor::DescriptorError),
+    /// Either writing to or loading from the persistence backend failed.
+    Persist(anyhow::Error),
+    /// Wallet is not initialized, persistence backend is empty.
+    NotInitialized,
+    /// The loaded genesis hash does not match what was provided.
+    LoadedGenesisDoesNotMatch {
+        /// The expected genesis block hash.
+        expected: BlockHash,
+        /// The block hash loaded from persistence.
+        got: Option<BlockHash>,
+    },
+    /// The loaded network type does not match what was provided.
+    LoadedNetworkDoesNotMatch {
+        /// The expected network type.
+        expected: Network,
+        /// The network type loaded from persistence.
+        got: Option<Network>,
+    },
+    /// The loaded desccriptor does not match what was provided.
+    LoadedDescriptorDoesNotMatch {
+        /// The descriptor loaded from persistence.
+        got: Option<ExtendedDescriptor>,
+        /// The keychain of the descriptor not matching
+        keychain: KeychainKind,
+    },
+}
+
+impl fmt::Display for NewOrLoadError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            NewOrLoadError::Descriptor(e) => e.fmt(f),
+            NewOrLoadError::Persist(e) => write!(
+                f,
+                "failed to either write to or load from persistence, {}",
+                e
+            ),
+            NewOrLoadError::NotInitialized => {
+                write!(f, "wallet is not initialized, persistence backend is empty")
+            }
+            NewOrLoadError::LoadedGenesisDoesNotMatch { expected, got } => {
+                write!(f, "loaded genesis hash is not {}, got {:?}", expected, got)
+            }
+            NewOrLoadError::LoadedNetworkDoesNotMatch { expected, got } => {
+                write!(f, "loaded network type is not {}, got {:?}", expected, got)
+            }
+            NewOrLoadError::LoadedDescriptorDoesNotMatch { got, keychain } => {
+                write!(
+                    f,
+                    "loaded descriptor is different from what was provided, got {:?} for keychain {:?}",
+                    got, keychain
+                )
+            }
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for NewOrLoadError {}
+
+/// An error that may occur when inserting a transaction into [`Wallet`].
+#[derive(Debug)]
+pub enum InsertTxError {
+    /// The error variant that occurs when the caller attempts to insert a transaction with a
+    /// confirmation height that is greater than the internal chain tip.
+    ConfirmationHeightCannotBeGreaterThanTip {
+        /// The internal chain's tip height.
+        tip_height: u32,
+        /// The introduced transaction's confirmation height.
+        tx_height: u32,
+    },
+}
+
+impl fmt::Display for InsertTxError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            InsertTxError::ConfirmationHeightCannotBeGreaterThanTip {
+                tip_height,
+                tx_height,
+            } => {
+                write!(f, "cannot insert tx with confirmation height ({}) higher than internal tip height ({})", tx_height, tip_height)
+            }
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for InsertTxError {}
+
+/// An error that may occur when applying a block to [`Wallet`].
+#[derive(Debug)]
+pub enum ApplyBlockError {
+    /// Occurs when the update chain cannot connect with original chain.
+    CannotConnect(CannotConnectError),
+    /// Occurs when the `connected_to` hash does not match the hash derived from `block`.
+    UnexpectedConnectedToHash {
+        /// Block hash of `connected_to`.
+        connected_to_hash: BlockHash,
+        /// Expected block hash of `connected_to`, as derived from `block`.
+        expected_hash: BlockHash,
+    },
+}
+
+impl fmt::Display for ApplyBlockError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            ApplyBlockError::CannotConnect(err) => err.fmt(f),
+            ApplyBlockError::UnexpectedConnectedToHash {
+                expected_hash: block_hash,
+                connected_to_hash: checkpoint_hash,
+            } => write!(
+                f,
+                "`connected_to` hash {} differs from the expected hash {} (which is derived from `block`)",
+                checkpoint_hash, block_hash
+            ),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for ApplyBlockError {}
+
+impl Wallet {
+    /// Initialize an empty [`Wallet`].
+    pub fn new<E: IntoWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
+        network: Network,
+    ) -> Result<Self, NewError> {
+        let genesis_hash = genesis_block(network).block_hash();
+        Self::new_with_genesis_hash(descriptor, change_descriptor, db, network, genesis_hash)
+    }
+
+    /// Initialize an empty [`Wallet`] with a custom genesis hash.
+    ///
+    /// This is like [`Wallet::new`] with an additional `genesis_hash` parameter. This is useful
+    /// for syncing from alternative networks.
+    pub fn new_with_genesis_hash<E: IntoWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        mut db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
+        network: Network,
+        genesis_hash: BlockHash,
+    ) -> Result<Self, NewError> {
+        if let Ok(changeset) = db.load_from_persistence() {
+            if changeset.is_some() {
+                return Err(NewError::NonEmptyDatabase);
+            }
+        }
+        let secp = Secp256k1::new();
+        let (chain, chain_changeset) = LocalChain::from_genesis_hash(genesis_hash);
+        let mut index = KeychainTxOutIndex::<KeychainKind>::default();
+
+        let (signers, change_signers) =
+            create_signers(&mut index, &secp, descriptor, change_descriptor, network)
+                .map_err(NewError::Descriptor)?;
+
+        let indexed_graph = IndexedTxGraph::new(index);
+
+        let mut persist = Persist::new(db);
+        persist.stage(ChangeSet {
+            chain: chain_changeset,
+            indexed_tx_graph: indexed_graph.initial_changeset(),
+            network: Some(network),
+        });
+        persist.commit().map_err(NewError::Persist)?;
+
+        Ok(Wallet {
+            signers,
+            change_signers,
+            network,
+            chain,
+            indexed_graph,
+            persist,
+            secp,
+        })
+    }
+
+    /// Load [`Wallet`] from the given persistence backend.
+    ///
+    /// Note that the descriptor secret keys are not persisted to the db; this means that after
+    /// calling this method the [`Wallet`] **won't** know the secret keys, and as such, won't be
+    /// able to sign transactions.
+    ///
+    /// If you wish to use the wallet to sign transactions, you need to add the secret keys
+    /// manually to the [`Wallet`]:
+    ///
+    /// ```rust,no_run
+    /// # use bdk_wallet::Wallet;
+    /// # use bdk_wallet::signer::{SignersContainer, SignerOrdering};
+    /// # use bdk_wallet::descriptor::Descriptor;
+    /// # use bitcoin::key::Secp256k1;
+    /// # use bdk_wallet::KeychainKind;
+    /// # use bdk_file_store::Store;
+    /// #
+    /// # fn main() -> Result<(), anyhow::Error> {
+    /// # let temp_dir = tempfile::tempdir().expect("must create tempdir");
+    /// # let file_path = temp_dir.path().join("store.db");
+    /// # let db: Store<bdk_wallet::wallet::ChangeSet> = Store::create_new(&[], &file_path).expect("must create db");
+    /// let secp = Secp256k1::new();
+    ///
+    /// let (external_descriptor, external_keymap) = Descriptor::parse_descriptor(&secp, "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)").unwrap();
+    /// let (internal_descriptor, internal_keymap) = Descriptor::parse_descriptor(&secp, "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)").unwrap();
+    ///
+    /// let external_signer_container = SignersContainer::build(external_keymap, &external_descriptor, &secp);
+    /// let internal_signer_container = SignersContainer::build(internal_keymap, &internal_descriptor, &secp);
+    ///
+    /// let mut wallet = Wallet::load(db)?;
+    ///
+    /// external_signer_container.signers().into_iter()
+    ///     .for_each(|s| wallet.add_signer(KeychainKind::External, SignerOrdering::default(), s.clone()));
+    /// internal_signer_container.signers().into_iter()
+    ///     .for_each(|s| wallet.add_signer(KeychainKind::Internal, SignerOrdering::default(), s.clone()));
+    /// # Ok(())
+    /// # }
+    /// ```
+    ///
+    /// Alternatively, you can call [`Wallet::new_or_load`], which will add the private keys of the
+    /// passed-in descriptors to the [`Wallet`].
+    pub fn load(
+        mut db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
+    ) -> Result<Self, LoadError> {
+        let changeset = db
+            .load_from_persistence()
+            .map_err(LoadError::Persist)?
+            .ok_or(LoadError::NotInitialized)?;
+        Self::load_from_changeset(db, changeset)
+    }
+
+    fn load_from_changeset(
+        db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
+        changeset: ChangeSet,
+    ) -> Result<Self, LoadError> {
+        let secp = Secp256k1::new();
+        let network = changeset.network.ok_or(LoadError::MissingNetwork)?;
+        let chain =
+            LocalChain::from_changeset(changeset.chain).map_err(|_| LoadError::MissingGenesis)?;
+        let mut index = KeychainTxOutIndex::<KeychainKind>::default();
+        let descriptor = changeset
+            .indexed_tx_graph
+            .indexer
+            .keychains_added
+            .get(&KeychainKind::External)
+            .ok_or(LoadError::MissingDescriptor)?
+            .clone();
+        let change_descriptor = changeset
+            .indexed_tx_graph
+            .indexer
+            .keychains_added
+            .get(&KeychainKind::Internal)
+            .cloned();
+
+        let (signers, change_signers) =
+            create_signers(&mut index, &secp, descriptor, change_descriptor, network)
+                .expect("Can't fail: we passed in valid descriptors, recovered from the changeset");
+
+        let mut indexed_graph = IndexedTxGraph::new(index);
+        indexed_graph.apply_changeset(changeset.indexed_tx_graph);
+
+        let persist = Persist::new(db);
+
+        Ok(Wallet {
+            signers,
+            change_signers,
+            chain,
+            indexed_graph,
+            persist,
+            network,
+            secp,
+        })
+    }
+
+    /// Either loads [`Wallet`] from persistence, or initializes it if it does not exist.
+    ///
+    /// This method will fail if the loaded [`Wallet`] has different parameters to those provided.
+    pub fn new_or_load<E: IntoWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
+        network: Network,
+    ) -> Result<Self, NewOrLoadError> {
+        let genesis_hash = genesis_block(network).block_hash();
+        Self::new_or_load_with_genesis_hash(
+            descriptor,
+            change_descriptor,
+            db,
+            network,
+            genesis_hash,
+        )
+    }
+
+    /// Either loads [`Wallet`] from persistence, or initializes it if it does not exist, using the
+    /// provided descriptor, change descriptor, network, and custom genesis hash.
+    ///
+    /// This method will fail if the loaded [`Wallet`] has different parameters to those provided.
+    /// This is like [`Wallet::new_or_load`] with an additional `genesis_hash` parameter. This is
+    /// useful for syncing from alternative networks.
+    pub fn new_or_load_with_genesis_hash<E: IntoWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        mut db: impl PersistBackend<ChangeSet> + Send + Sync + 'static,
+        network: Network,
+        genesis_hash: BlockHash,
+    ) -> Result<Self, NewOrLoadError> {
+        let changeset = db
+            .load_from_persistence()
+            .map_err(NewOrLoadError::Persist)?;
+        match changeset {
+            Some(changeset) => {
+                let mut wallet = Self::load_from_changeset(db, changeset).map_err(|e| match e {
+                    LoadError::Descriptor(e) => NewOrLoadError::Descriptor(e),
+                    LoadError::Persist(e) => NewOrLoadError::Persist(e),
+                    LoadError::NotInitialized => NewOrLoadError::NotInitialized,
+                    LoadError::MissingNetwork => NewOrLoadError::LoadedNetworkDoesNotMatch {
+                        expected: network,
+                        got: None,
+                    },
+                    LoadError::MissingGenesis => NewOrLoadError::LoadedGenesisDoesNotMatch {
+                        expected: genesis_hash,
+                        got: None,
+                    },
+                    LoadError::MissingDescriptor => NewOrLoadError::LoadedDescriptorDoesNotMatch {
+                        got: None,
+                        keychain: KeychainKind::External,
+                    },
+                })?;
+                if wallet.network != network {
+                    return Err(NewOrLoadError::LoadedNetworkDoesNotMatch {
+                        expected: network,
+                        got: Some(wallet.network),
+                    });
+                }
+                if wallet.chain.genesis_hash() != genesis_hash {
+                    return Err(NewOrLoadError::LoadedGenesisDoesNotMatch {
+                        expected: genesis_hash,
+                        got: Some(wallet.chain.genesis_hash()),
+                    });
+                }
+
+                let (expected_descriptor, expected_descriptor_keymap) = descriptor
+                    .into_wallet_descriptor(&wallet.secp, network)
+                    .map_err(NewOrLoadError::Descriptor)?;
+                let wallet_descriptor = wallet.public_descriptor(KeychainKind::External).cloned();
+                if wallet_descriptor != Some(expected_descriptor.clone()) {
+                    return Err(NewOrLoadError::LoadedDescriptorDoesNotMatch {
+                        got: wallet_descriptor,
+                        keychain: KeychainKind::External,
+                    });
+                }
+                // if expected descriptor has private keys add them as new signers
+                if !expected_descriptor_keymap.is_empty() {
+                    let signer_container = SignersContainer::build(
+                        expected_descriptor_keymap,
+                        &expected_descriptor,
+                        &wallet.secp,
+                    );
+                    signer_container.signers().into_iter().for_each(|signer| {
+                        wallet.add_signer(
+                            KeychainKind::External,
+                            SignerOrdering::default(),
+                            signer.clone(),
+                        )
+                    });
+                }
+
+                let expected_change_descriptor = if let Some(c) = change_descriptor {
+                    Some(
+                        c.into_wallet_descriptor(&wallet.secp, network)
+                            .map_err(NewOrLoadError::Descriptor)?,
+                    )
+                } else {
+                    None
+                };
+                let wallet_change_descriptor =
+                    wallet.public_descriptor(KeychainKind::Internal).cloned();
+
+                match (expected_change_descriptor, wallet_change_descriptor) {
+                    (Some((expected_descriptor, expected_keymap)), Some(wallet_descriptor))
+                        if wallet_descriptor == expected_descriptor =>
+                    {
+                        // if expected change descriptor has private keys add them as new signers
+                        if !expected_keymap.is_empty() {
+                            let signer_container = SignersContainer::build(
+                                expected_keymap,
+                                &expected_descriptor,
+                                &wallet.secp,
+                            );
+                            signer_container.signers().into_iter().for_each(|signer| {
+                                wallet.add_signer(
+                                    KeychainKind::Internal,
+                                    SignerOrdering::default(),
+                                    signer.clone(),
+                                )
+                            });
+                        }
+                    }
+                    (None, None) => (),
+                    (_, wallet_descriptor) => {
+                        return Err(NewOrLoadError::LoadedDescriptorDoesNotMatch {
+                            got: wallet_descriptor,
+                            keychain: KeychainKind::Internal,
+                        });
+                    }
+                }
+
+                Ok(wallet)
+            }
+            None => Self::new_with_genesis_hash(
+                descriptor,
+                change_descriptor,
+                db,
+                network,
+                genesis_hash,
+            )
+            .map_err(|e| match e {
+                NewError::NonEmptyDatabase => {
+                    unreachable!("database is already checked to have no data")
+                }
+                NewError::Descriptor(e) => NewOrLoadError::Descriptor(e),
+                NewError::Persist(e) => NewOrLoadError::Persist(e),
+            }),
+        }
+    }
+
+    /// Get the Bitcoin network the wallet is using.
+    pub fn network(&self) -> Network {
+        self.network
+    }
+
+    /// Iterator over all keychains in this wallet
+    pub fn keychains(&self) -> impl Iterator<Item = (&KeychainKind, &ExtendedDescriptor)> {
+        self.indexed_graph.index.keychains()
+    }
+
+    /// Peek an address of the given `keychain` at `index` without revealing it.
+    ///
+    /// For non-wildcard descriptors this returns the same address at every provided index.
+    ///
+    /// # Panics
+    ///
+    /// This panics when the caller requests for an address of derivation index greater than the
+    /// [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) max index.
+    pub fn peek_address(&self, keychain: KeychainKind, mut index: u32) -> AddressInfo {
+        let keychain = self.map_keychain(keychain);
+        let mut spk_iter = self
+            .indexed_graph
+            .index
+            .unbounded_spk_iter(&keychain)
+            .expect("Must exist (we called map_keychain)");
+        if !spk_iter.descriptor().has_wildcard() {
+            index = 0;
+        }
+        let (index, spk) = spk_iter
+            .nth(index as usize)
+            .expect("derivation index is out of bounds");
+
+        AddressInfo {
+            index,
+            address: Address::from_script(&spk, self.network).expect("must have address form"),
+            keychain,
+        }
+    }
+
+    /// Attempt to reveal the next address of the given `keychain`.
+    ///
+    /// This will increment the internal derivation index. If the keychain's descriptor doesn't
+    /// contain a wildcard or every address is already revealed up to the maximum derivation
+    /// index defined in [BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki),
+    /// then returns the last revealed address.
+    ///
+    /// # Errors
+    ///
+    /// If writing to persistent storage fails.
+    pub fn reveal_next_address(&mut self, keychain: KeychainKind) -> anyhow::Result<AddressInfo> {
+        let keychain = self.map_keychain(keychain);
+        let ((index, spk), index_changeset) = self
+            .indexed_graph
+            .index
+            .reveal_next_spk(&keychain)
+            .expect("Must exist (we called map_keychain)");
+
+        self.persist
+            .stage_and_commit(indexed_tx_graph::ChangeSet::from(index_changeset).into())?;
+
+        Ok(AddressInfo {
+            index,
+            address: Address::from_script(spk, self.network).expect("must have address form"),
+            keychain,
+        })
+    }
+
+    /// Reveal addresses up to and including the target `index` and return an iterator
+    /// of newly revealed addresses.
+    ///
+    /// If the target `index` is unreachable, we make a best effort to reveal up to the last
+    /// possible index. If all addresses up to the given `index` are already revealed, then
+    /// no new addresses are returned.
+    ///
+    /// # Errors
+    ///
+    /// If writing to persistent storage fails.
+    pub fn reveal_addresses_to(
+        &mut self,
+        keychain: KeychainKind,
+        index: u32,
+    ) -> anyhow::Result<impl Iterator<Item = AddressInfo> + '_> {
+        let keychain = self.map_keychain(keychain);
+        let (spk_iter, index_changeset) = self
+            .indexed_graph
+            .index
+            .reveal_to_target(&keychain, index)
+            .expect("must exist (we called map_keychain)");
+
+        self.persist
+            .stage_and_commit(indexed_tx_graph::ChangeSet::from(index_changeset).into())?;
+
+        Ok(spk_iter.map(move |(index, spk)| AddressInfo {
+            index,
+            address: Address::from_script(&spk, self.network).expect("must have address form"),
+            keychain,
+        }))
+    }
+
+    /// Get the next unused address for the given `keychain`, i.e. the address with the lowest
+    /// derivation index that hasn't been used.
+    ///
+    /// This will attempt to derive and reveal a new address if no newly revealed addresses
+    /// are available. See also [`reveal_next_address`](Self::reveal_next_address).
+    ///
+    /// # Errors
+    ///
+    /// If writing to persistent storage fails.
+    pub fn next_unused_address(&mut self, keychain: KeychainKind) -> anyhow::Result<AddressInfo> {
+        let keychain = self.map_keychain(keychain);
+        let ((index, spk), index_changeset) = self
+            .indexed_graph
+            .index
+            .next_unused_spk(&keychain)
+            .expect("must exist (we called map_keychain)");
+
+        self.persist
+            .stage_and_commit(indexed_tx_graph::ChangeSet::from(index_changeset).into())?;
+
+        Ok(AddressInfo {
+            index,
+            address: Address::from_script(spk, self.network).expect("must have address form"),
+            keychain,
+        })
+    }
+
+    /// Marks an address used of the given `keychain` at `index`.
+    ///
+    /// Returns whether the given index was present and then removed from the unused set.
+    pub fn mark_used(&mut self, keychain: KeychainKind, index: u32) -> bool {
+        self.indexed_graph.index.mark_used(keychain, index)
+    }
+
+    /// Undoes the effect of [`mark_used`] and returns whether the `index` was inserted
+    /// back into the unused set.
+    ///
+    /// Since this is only a superficial marker, it will have no effect if the address at the given
+    /// `index` was actually used, i.e. the wallet has previously indexed a tx output for the
+    /// derived spk.
+    ///
+    /// [`mark_used`]: Self::mark_used
+    pub fn unmark_used(&mut self, keychain: KeychainKind, index: u32) -> bool {
+        self.indexed_graph.index.unmark_used(keychain, index)
+    }
+
+    /// List addresses that are revealed but unused.
+    ///
+    /// Note if the returned iterator is empty you can reveal more addresses
+    /// by using [`reveal_next_address`](Self::reveal_next_address) or
+    /// [`reveal_addresses_to`](Self::reveal_addresses_to).
+    pub fn list_unused_addresses(
+        &self,
+        keychain: KeychainKind,
+    ) -> impl DoubleEndedIterator<Item = AddressInfo> + '_ {
+        let keychain = self.map_keychain(keychain);
+        self.indexed_graph
+            .index
+            .unused_keychain_spks(&keychain)
+            .map(move |(index, spk)| AddressInfo {
+                index,
+                address: Address::from_script(spk, self.network).expect("must have address form"),
+                keychain,
+            })
+    }
+
+    /// Return whether or not a `script` is part of this wallet (either internal or external)
+    pub fn is_mine(&self, script: &Script) -> bool {
+        self.indexed_graph.index.index_of_spk(script).is_some()
+    }
+
+    /// 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.indexed_graph.index.index_of_spk(spk)
+    }
+
+    /// Return the list of unspent outputs of this wallet
+    pub fn list_unspent(&self) -> impl Iterator<Item = LocalOutput> + '_ {
+        self.indexed_graph
+            .graph()
+            .filter_chain_unspents(
+                &self.chain,
+                self.chain.tip().block_id(),
+                self.indexed_graph.index.outpoints(),
+            )
+            .map(|((k, i), full_txo)| new_local_utxo(k, i, full_txo))
+    }
+
+    /// List all relevant outputs (includes both spent and unspent, confirmed and unconfirmed).
+    ///
+    /// To list only unspent outputs (UTXOs), use [`Wallet::list_unspent`] instead.
+    pub fn list_output(&self) -> impl Iterator<Item = LocalOutput> + '_ {
+        self.indexed_graph
+            .graph()
+            .filter_chain_txouts(
+                &self.chain,
+                self.chain.tip().block_id(),
+                self.indexed_graph.index.outpoints(),
+            )
+            .map(|((k, i), full_txo)| new_local_utxo(k, i, full_txo))
+    }
+
+    /// Get all the checkpoints the wallet is currently storing indexed by height.
+    pub fn checkpoints(&self) -> CheckPointIter {
+        self.chain.iter_checkpoints()
+    }
+
+    /// Returns the latest checkpoint.
+    pub fn latest_checkpoint(&self) -> CheckPoint {
+        self.chain.tip()
+    }
+
+    /// Get unbounded script pubkey iterators for both `Internal` and `External` keychains.
+    ///
+    /// This is intended 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 gap*.
+    ///
+    /// Note carefully that iterators go over **all** script pubkeys on the keychains (not what
+    /// script pubkeys the wallet is storing internally).
+    pub fn all_unbounded_spk_iters(
+        &self,
+    ) -> BTreeMap<KeychainKind, impl Iterator<Item = (u32, ScriptBuf)> + Clone> {
+        self.indexed_graph.index.all_unbounded_spk_iters()
+    }
+
+    /// Get an unbounded script pubkey iterator for the given `keychain`.
+    ///
+    /// See [`all_unbounded_spk_iters`] for more documentation
+    ///
+    /// [`all_unbounded_spk_iters`]: Self::all_unbounded_spk_iters
+    pub fn unbounded_spk_iter(
+        &self,
+        keychain: KeychainKind,
+    ) -> impl Iterator<Item = (u32, ScriptBuf)> + Clone {
+        let keychain = self.map_keychain(keychain);
+        self.indexed_graph
+            .index
+            .unbounded_spk_iter(&keychain)
+            .expect("Must exist (we called map_keychain)")
+    }
+
+    /// Returns the utxo owned by this wallet corresponding to `outpoint` if it exists in the
+    /// wallet's database.
+    pub fn get_utxo(&self, op: OutPoint) -> Option<LocalOutput> {
+        let (keychain, index, _) = self.indexed_graph.index.txout(op)?;
+        self.indexed_graph
+            .graph()
+            .filter_chain_unspents(
+                &self.chain,
+                self.chain.tip().block_id(),
+                core::iter::once(((), op)),
+            )
+            .map(|(_, full_txo)| new_local_utxo(keychain, index, full_txo))
+            .next()
+    }
+
+    /// Inserts a [`TxOut`] at [`OutPoint`] into the wallet's transaction graph.
+    ///
+    /// This is used for providing a previous output's value so that we can use [`calculate_fee`]
+    /// or [`calculate_fee_rate`] on a given transaction. Outputs inserted with this method will
+    /// not be returned in [`list_unspent`] or [`list_output`].
+    ///
+    /// Any inserted `TxOut`s are not persisted until [`commit`] is called.
+    ///
+    /// **WARNING:** This should only be used to add `TxOut`s that the wallet does not own. Only
+    /// insert `TxOut`s that you trust the values for!
+    ///
+    /// [`calculate_fee`]: Self::calculate_fee
+    /// [`calculate_fee_rate`]: Self::calculate_fee_rate
+    /// [`list_unspent`]: Self::list_unspent
+    /// [`list_output`]: Self::list_output
+    /// [`commit`]: Self::commit
+    pub fn insert_txout(&mut self, outpoint: OutPoint, txout: TxOut) {
+        let additions = self.indexed_graph.insert_txout(outpoint, txout);
+        self.persist.stage(ChangeSet::from(additions));
+    }
+
+    /// Calculates the fee of a given transaction. Returns 0 if `tx` is a coinbase transaction.
+    ///
+    /// To calculate the fee for a [`Transaction`] with inputs not owned by this wallet you must
+    /// manually insert the TxOut(s) into the tx graph using the [`insert_txout`] function.
+    ///
+    /// Note `tx` does not have to be in the graph for this to work.
+    ///
+    /// # Examples
+    ///
+    /// ```rust, no_run
+    /// # use bitcoin::Txid;
+    /// # use bdk_wallet::Wallet;
+    /// # let mut wallet: Wallet = todo!();
+    /// # let txid:Txid = todo!();
+    /// let tx = wallet.get_tx(txid).expect("transaction").tx_node.tx;
+    /// let fee = wallet.calculate_fee(&tx).expect("fee");
+    /// ```
+    ///
+    /// ```rust, no_run
+    /// # use bitcoin::Psbt;
+    /// # use bdk_wallet::Wallet;
+    /// # let mut wallet: Wallet = todo!();
+    /// # let mut psbt: Psbt = todo!();
+    /// let tx = &psbt.clone().extract_tx().expect("tx");
+    /// let fee = wallet.calculate_fee(tx).expect("fee");
+    /// ```
+    /// [`insert_txout`]: Self::insert_txout
+    pub fn calculate_fee(&self, tx: &Transaction) -> Result<u64, CalculateFeeError> {
+        self.indexed_graph.graph().calculate_fee(tx)
+    }
+
+    /// Calculate the [`FeeRate`] for a given transaction.
+    ///
+    /// To calculate the fee rate for a [`Transaction`] with inputs not owned by this wallet you must
+    /// manually insert the TxOut(s) into the tx graph using the [`insert_txout`] function.
+    ///
+    /// Note `tx` does not have to be in the graph for this to work.
+    ///
+    /// # Examples
+    ///
+    /// ```rust, no_run
+    /// # use bitcoin::Txid;
+    /// # use bdk_wallet::Wallet;
+    /// # let mut wallet: Wallet = todo!();
+    /// # let txid:Txid = todo!();
+    /// let tx = wallet.get_tx(txid).expect("transaction").tx_node.tx;
+    /// let fee_rate = wallet.calculate_fee_rate(&tx).expect("fee rate");
+    /// ```
+    ///
+    /// ```rust, no_run
+    /// # use bitcoin::Psbt;
+    /// # use bdk_wallet::Wallet;
+    /// # let mut wallet: Wallet = todo!();
+    /// # let mut psbt: Psbt = todo!();
+    /// let tx = &psbt.clone().extract_tx().expect("tx");
+    /// let fee_rate = wallet.calculate_fee_rate(tx).expect("fee rate");
+    /// ```
+    /// [`insert_txout`]: Self::insert_txout
+    pub fn calculate_fee_rate(&self, tx: &Transaction) -> Result<FeeRate, CalculateFeeError> {
+        self.calculate_fee(tx)
+            .map(|fee| Amount::from_sat(fee) / tx.weight())
+    }
+
+    /// Compute the `tx`'s sent and received [`Amount`]s.
+    ///
+    /// This method returns a tuple `(sent, received)`. Sent is the sum of the txin amounts
+    /// that spend from previous txouts tracked by this wallet. Received is the summation
+    /// of this tx's outputs that send to script pubkeys tracked by this wallet.
+    ///
+    /// # Examples
+    ///
+    /// ```rust, no_run
+    /// # use bitcoin::Txid;
+    /// # use bdk_wallet::Wallet;
+    /// # let mut wallet: Wallet = todo!();
+    /// # let txid:Txid = todo!();
+    /// let tx = wallet.get_tx(txid).expect("tx exists").tx_node.tx;
+    /// let (sent, received) = wallet.sent_and_received(&tx);
+    /// ```
+    ///
+    /// ```rust, no_run
+    /// # use bitcoin::Psbt;
+    /// # use bdk_wallet::Wallet;
+    /// # let mut wallet: Wallet = todo!();
+    /// # let mut psbt: Psbt = todo!();
+    /// let tx = &psbt.clone().extract_tx().expect("tx");
+    /// let (sent, received) = wallet.sent_and_received(tx);
+    /// ```
+    pub fn sent_and_received(&self, tx: &Transaction) -> (Amount, Amount) {
+        self.indexed_graph.index.sent_and_received(tx, ..)
+    }
+
+    /// Get a single transaction from the wallet as a [`CanonicalTx`] (if the transaction exists).
+    ///
+    /// `CanonicalTx` contains the full transaction alongside meta-data such as:
+    /// * Blocks that the transaction is [`Anchor`]ed in. These may or may not be blocks that exist
+    ///   in the best chain.
+    /// * The [`ChainPosition`] of the transaction in the best chain - whether the transaction is
+    ///   confirmed or unconfirmed. If the transaction is confirmed, the anchor which proves the
+    ///   confirmation is provided. If the transaction is unconfirmed, the unix timestamp of when
+    ///   the transaction was last seen in the mempool is provided.
+    ///
+    /// ```rust, no_run
+    /// use bdk_chain::Anchor;
+    /// use bdk_wallet::{chain::ChainPosition, Wallet};
+    /// # let wallet: Wallet = todo!();
+    /// # let my_txid: bitcoin::Txid = todo!();
+    ///
+    /// let canonical_tx = wallet.get_tx(my_txid).expect("panic if tx does not exist");
+    ///
+    /// // get reference to full transaction
+    /// println!("my tx: {:#?}", canonical_tx.tx_node.tx);
+    ///
+    /// // list all transaction anchors
+    /// for anchor in canonical_tx.tx_node.anchors {
+    ///     println!(
+    ///         "tx is anchored by block of hash {}",
+    ///         anchor.anchor_block().hash
+    ///     );
+    /// }
+    ///
+    /// // get confirmation status of transaction
+    /// match canonical_tx.chain_position {
+    ///     ChainPosition::Confirmed(anchor) => println!(
+    ///         "tx is confirmed at height {}, we know this since {}:{} is in the best chain",
+    ///         anchor.confirmation_height, anchor.anchor_block.height, anchor.anchor_block.hash,
+    ///     ),
+    ///     ChainPosition::Unconfirmed(last_seen) => println!(
+    ///         "tx is last seen at {}, it is unconfirmed as it is not anchored in the best chain",
+    ///         last_seen,
+    ///     ),
+    /// }
+    /// ```
+    ///
+    /// [`Anchor`]: bdk_chain::Anchor
+    pub fn get_tx(
+        &self,
+        txid: Txid,
+    ) -> Option<CanonicalTx<'_, Arc<Transaction>, ConfirmationTimeHeightAnchor>> {
+        let graph = self.indexed_graph.graph();
+
+        Some(CanonicalTx {
+            chain_position: graph.get_chain_position(
+                &self.chain,
+                self.chain.tip().block_id(),
+                txid,
+            )?,
+            tx_node: graph.get_tx_node(txid)?,
+        })
+    }
+
+    /// 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).
+    ///
+    /// [`commit`]: Self::commit
+    pub fn insert_checkpoint(
+        &mut self,
+        block_id: BlockId,
+    ) -> Result<bool, local_chain::AlterCheckPointError> {
+        let changeset = self.chain.insert_block(block_id)?;
+        let changed = !changeset.is_empty();
+        self.persist.stage(changeset.into());
+        Ok(changed)
+    }
+
+    /// Add a transaction to the wallet's internal view of the chain. This stages but does not
+    /// [`commit`] the change.
+    ///
+    /// Returns whether anything changed with the transaction insertion (e.g. `false` if the
+    /// transaction was already inserted at the same position).
+    ///
+    /// A `tx` can be rejected if `position` has a height greater than the [`latest_checkpoint`].
+    /// Therefore you should use [`insert_checkpoint`] to insert new checkpoints before manually
+    /// inserting new transactions.
+    ///
+    /// **WARNING:** If `position` is confirmed, we anchor the `tx` to a the lowest checkpoint that
+    /// is >= the `position`'s height. The caller is responsible for ensuring the `tx` exists in our
+    /// local view of the best chain's history.
+    ///
+    /// [`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, InsertTxError> {
+        let (anchor, last_seen) = match position {
+            ConfirmationTime::Confirmed { height, time } => {
+                // anchor tx to checkpoint with lowest height that is >= position's height
+                let anchor = self
+                    .chain
+                    .range(height..)
+                    .last()
+                    .ok_or(InsertTxError::ConfirmationHeightCannotBeGreaterThanTip {
+                        tip_height: self.chain.tip().height(),
+                        tx_height: height,
+                    })
+                    .map(|anchor_cp| ConfirmationTimeHeightAnchor {
+                        anchor_block: anchor_cp.block_id(),
+                        confirmation_height: height,
+                        confirmation_time: time,
+                    })?;
+
+                (Some(anchor), None)
+            }
+            ConfirmationTime::Unconfirmed { last_seen } => (None, Some(last_seen)),
+        };
+
+        let mut changeset = ChangeSet::default();
+        let txid = tx.txid();
+        changeset.append(self.indexed_graph.insert_tx(tx).into());
+        if let Some(anchor) = anchor {
+            changeset.append(self.indexed_graph.insert_anchor(txid, anchor).into());
+        }
+        if let Some(last_seen) = last_seen {
+            changeset.append(self.indexed_graph.insert_seen_at(txid, last_seen).into());
+        }
+
+        let changed = !changeset.is_empty();
+        self.persist.stage(changeset);
+        Ok(changed)
+    }
+
+    /// Iterate over the transactions in the wallet.
+    pub fn transactions(
+        &self,
+    ) -> impl Iterator<Item = CanonicalTx<'_, Arc<Transaction>, ConfirmationTimeHeightAnchor>> + '_
+    {
+        self.indexed_graph
+            .graph()
+            .list_chain_txs(&self.chain, self.chain.tip().block_id())
+    }
+
+    /// Return the balance, separated into available, trusted-pending, untrusted-pending and immature
+    /// values.
+    pub fn get_balance(&self) -> Balance {
+        self.indexed_graph.graph().balance(
+            &self.chain,
+            self.chain.tip().block_id(),
+            self.indexed_graph.index.outpoints(),
+            |&(k, _), _| k == KeychainKind::Internal,
+        )
+    }
+
+    /// Add an external signer
+    ///
+    /// See [the `signer` module](signer) for an example.
+    pub fn add_signer(
+        &mut self,
+        keychain: KeychainKind,
+        ordering: SignerOrdering,
+        signer: Arc<dyn TransactionSigner>,
+    ) {
+        let signers = match keychain {
+            KeychainKind::External => Arc::make_mut(&mut self.signers),
+            KeychainKind::Internal => Arc::make_mut(&mut self.change_signers),
+        };
+
+        signers.add_external(signer.id(&self.secp), ordering, signer);
+    }
+
+    /// Get the signers
+    ///
+    /// ## Example
+    ///
+    /// ```
+    /// # use bdk_wallet::{Wallet, KeychainKind};
+    /// # use bdk_wallet::bitcoin::Network;
+    /// 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>>(())
+    /// ```
+    pub fn get_signers(&self, keychain: KeychainKind) -> Arc<SignersContainer> {
+        match keychain {
+            KeychainKind::External => Arc::clone(&self.signers),
+            KeychainKind::Internal => Arc::clone(&self.change_signers),
+        }
+    }
+
+    /// Start building a transaction.
+    ///
+    /// This returns a blank [`TxBuilder`] from which you can specify the parameters for the transaction.
+    ///
+    /// ## Example
+    ///
+    /// ```
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk_wallet::*;
+    /// # use bdk_wallet::wallet::ChangeSet;
+    /// # use bdk_wallet::wallet::error::CreateTxError;
+    /// # use bdk_persist::PersistBackend;
+    /// # use anyhow::Error;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let mut wallet = doctest_wallet!();
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
+    /// let psbt = {
+    ///    let mut builder =  wallet.build_tx();
+    ///    builder
+    ///        .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
+    ///    builder.finish()?
+    /// };
+    ///
+    /// // sign and broadcast ...
+    /// # Ok::<(), anyhow::Error>(())
+    /// ```
+    ///
+    /// [`TxBuilder`]: crate::TxBuilder
+    pub fn build_tx(&mut self) -> TxBuilder<'_, DefaultCoinSelectionAlgorithm, CreateTx> {
+        TxBuilder {
+            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>(
+        &mut self,
+        coin_selection: Cs,
+        params: TxParams,
+    ) -> Result<Psbt, CreateTxError> {
+        let keychains: BTreeMap<_, _> = self.indexed_graph.index.keychains().collect();
+        let external_descriptor = keychains.get(&KeychainKind::External).expect("must exist");
+        let internal_descriptor = keychains.get(&KeychainKind::Internal);
+
+        let external_policy = external_descriptor
+            .extract_policy(&self.signers, BuildSatisfaction::None, &self.secp)?
+            .unwrap();
+        let internal_policy = internal_descriptor
+            .as_ref()
+            .map(|desc| {
+                Ok::<_, CreateTxError>(
+                    desc.extract_policy(&self.change_signers, BuildSatisfaction::None, &self.secp)?
+                        .unwrap(),
+                )
+            })
+            .transpose()?;
+
+        // The policy allows spending external outputs, but it requires a policy path that hasn't been
+        // provided
+        if params.change_policy != tx_builder::ChangeSpendPolicy::OnlyChange
+            && external_policy.requires_path()
+            && params.external_policy_path.is_none()
+        {
+            return Err(CreateTxError::SpendingPolicyRequired(
+                KeychainKind::External,
+            ));
+        };
+        // Same for the internal_policy path, if present
+        if let Some(internal_policy) = &internal_policy {
+            if params.change_policy != tx_builder::ChangeSpendPolicy::ChangeForbidden
+                && internal_policy.requires_path()
+                && params.internal_policy_path.is_none()
+            {
+                return Err(CreateTxError::SpendingPolicyRequired(
+                    KeychainKind::Internal,
+                ));
+            };
+        }
+
+        let external_requirements = external_policy.get_condition(
+            params
+                .external_policy_path
+                .as_ref()
+                .unwrap_or(&BTreeMap::new()),
+        )?;
+        let internal_requirements = internal_policy
+            .map(|policy| {
+                Ok::<_, CreateTxError>(
+                    policy.get_condition(
+                        params
+                            .internal_policy_path
+                            .as_ref()
+                            .unwrap_or(&BTreeMap::new()),
+                    )?,
+                )
+            })
+            .transpose()?;
+
+        let requirements =
+            external_requirements.merge(&internal_requirements.unwrap_or_default())?;
+
+        let version = match params.version {
+            Some(tx_builder::Version(0)) => return Err(CreateTxError::Version0),
+            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
+                return Err(CreateTxError::Version1Csv)
+            }
+            Some(tx_builder::Version(x)) => x,
+            None if requirements.csv.is_some() => 2,
+            None => 1,
+        };
+
+        // We use a match here instead of a unwrap_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 => {
+                let tip_height = self.chain.tip().height();
+                absolute::LockTime::from_height(tip_height).expect("invalid height")
+            }
+            Some(h) => h,
+        };
+
+        let lock_time = match params.locktime {
+            // When no nLockTime is specified, we try to prevent fee sniping, if possible
+            None => {
+                // Fee sniping can be partially prevented by setting the timelock
+                // to current_height. If we don't know the current_height,
+                // we default to 0.
+                let fee_sniping_height = current_height;
+
+                // We choose the biggest between the required nlocktime and the fee sniping
+                // height
+                match requirements.timelock {
+                    // No requirement, just use the fee_sniping_height
+                    None => fee_sniping_height,
+                    // There's a block-based requirement, but the value is lower than the fee_sniping_height
+                    Some(value @ absolute::LockTime::Blocks(_)) if value < fee_sniping_height => {
+                        fee_sniping_height
+                    }
+                    // There's a time-based requirement or a block-based requirement greater
+                    // than the fee_sniping_height use that value
+                    Some(value) => value,
+                }
+            }
+            // Specific nLockTime required and we have no constraints, so just set to that value
+            Some(x) if requirements.timelock.is_none() => x,
+            // Specific nLockTime required and it's compatible with the constraints
+            Some(x)
+                if requirements.timelock.unwrap().is_same_unit(x)
+                    && x >= requirements.timelock.unwrap() =>
+            {
+                x
+            }
+            // Invalid nLockTime required
+            Some(x) => {
+                return Err(CreateTxError::LockTime {
+                    requested: x,
+                    required: requirements.timelock.unwrap(),
+                })
+            }
+        };
+
+        // The nSequence to be by default for inputs unless an explicit sequence is specified.
+        let n_sequence = match (params.rbf, requirements.csv) {
+            // No RBF or CSV but there's an nLockTime, so the nSequence cannot be final
+            (None, None) if lock_time != absolute::LockTime::ZERO => {
+                Sequence::ENABLE_LOCKTIME_NO_RBF
+            }
+            // No RBF, CSV or nLockTime, make the transaction final
+            (None, None) => Sequence::MAX,
+
+            // No RBF requested, use the value from CSV. Note that this value is by definition
+            // non-final, so even if a timelock is enabled this nSequence is fine, hence why we
+            // don't bother checking for it here. The same is true for all the other branches below
+            (None, Some(csv)) => csv,
+
+            // RBF with a specific value but that value is too high
+            (Some(tx_builder::RbfValue::Value(rbf)), _) if !rbf.is_rbf() => {
+                return Err(CreateTxError::RbfSequence)
+            }
+            // RBF with a specific value requested, but the value is incompatible with CSV
+            (Some(tx_builder::RbfValue::Value(rbf)), Some(csv))
+                if !check_nsequence_rbf(rbf, csv) =>
+            {
+                return Err(CreateTxError::RbfSequenceCsv { rbf, csv })
+            }
+
+            // RBF enabled with the default value with CSV also enabled. CSV takes precedence
+            (Some(tx_builder::RbfValue::Default), Some(csv)) => csv,
+            // Valid RBF, either default or with a specific value. We ignore the `CSV` value
+            // because we've already checked it before
+            (Some(rbf), _) => rbf.get_value(),
+        };
+
+        let (fee_rate, mut fee_amount) = match params.fee_policy.unwrap_or_default() {
+            //FIXME: see https://github.com/bitcoindevkit/bdk/issues/256
+            FeePolicy::FeeAmount(fee) => {
+                if let Some(previous_fee) = params.bumping_fee {
+                    if fee < previous_fee.absolute {
+                        return Err(CreateTxError::FeeTooLow {
+                            required: previous_fee.absolute,
+                        });
+                    }
+                }
+                (FeeRate::ZERO, fee)
+            }
+            FeePolicy::FeeRate(rate) => {
+                if let Some(previous_fee) = params.bumping_fee {
+                    let required_feerate = FeeRate::from_sat_per_kwu(
+                        previous_fee.rate.to_sat_per_kwu()
+                            + FeeRate::BROADCAST_MIN.to_sat_per_kwu(), // +1 sat/vb
+                    );
+                    if rate < required_feerate {
+                        return Err(CreateTxError::FeeRateTooLow {
+                            required: required_feerate,
+                        });
+                    }
+                }
+                (rate, 0)
+            }
+        };
+
+        let mut tx = Transaction {
+            version: transaction::Version::non_standard(version),
+            lock_time,
+            input: vec![],
+            output: vec![],
+        };
+
+        if params.manually_selected_only && params.utxos.is_empty() {
+            return Err(CreateTxError::NoUtxosSelected);
+        }
+
+        // we keep it as a float while we accumulate it, and only round it at the end
+        let mut outgoing: u64 = 0;
+        let mut received: u64 = 0;
+
+        let recipients = params.recipients.iter().map(|(r, v)| (r, *v));
+
+        for (index, (script_pubkey, value)) in recipients.enumerate() {
+            if !params.allow_dust
+                && value.is_dust(script_pubkey)
+                && !script_pubkey.is_provably_unspendable()
+            {
+                return Err(CreateTxError::OutputBelowDustLimit(index));
+            }
+
+            if self.is_mine(script_pubkey) {
+                received += value;
+            }
+
+            let new_out = TxOut {
+                script_pubkey: script_pubkey.clone(),
+                value: Amount::from_sat(value),
+            };
+
+            tx.output.push(new_out);
+
+            outgoing += value;
+        }
+
+        fee_amount += (fee_rate * tx.weight()).to_sat();
+
+        if params.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
+            && internal_descriptor.is_none()
+        {
+            return Err(CreateTxError::ChangePolicyDescriptor);
+        }
+
+        let (required_utxos, optional_utxos) =
+            self.preselect_utxos(&params, Some(current_height.to_consensus_u32()));
+
+        // get drain script
+        let drain_script = match params.drain_to {
+            Some(ref drain_recipient) => drain_recipient.clone(),
+            None => {
+                let change_keychain = self.map_keychain(KeychainKind::Internal);
+                let ((index, spk), index_changeset) = self
+                    .indexed_graph
+                    .index
+                    .next_unused_spk(&change_keychain)
+                    .expect("Keychain exists (we called map_keychain)");
+                let spk = spk.into();
+                self.indexed_graph.index.mark_used(change_keychain, index);
+                self.persist
+                    .stage(ChangeSet::from(indexed_tx_graph::ChangeSet::from(
+                        index_changeset,
+                    )));
+                self.persist.commit().map_err(CreateTxError::Persist)?;
+                spk
+            }
+        };
+
+        let (required_utxos, optional_utxos) =
+            coin_selection::filter_duplicates(required_utxos, optional_utxos);
+
+        let coin_selection = coin_selection.coin_select(
+            required_utxos,
+            optional_utxos,
+            fee_rate,
+            outgoing + fee_amount,
+            &drain_script,
+        )?;
+        fee_amount += coin_selection.fee_amount;
+        let excess = &coin_selection.excess;
+
+        tx.input = coin_selection
+            .selected
+            .iter()
+            .map(|u| bitcoin::TxIn {
+                previous_output: u.outpoint(),
+                script_sig: ScriptBuf::default(),
+                sequence: u.sequence().unwrap_or(n_sequence),
+                witness: Witness::new(),
+            })
+            .collect();
+
+        if tx.output.is_empty() {
+            // Uh oh, our transaction has no outputs.
+            // We allow this when:
+            // - We have a drain_to address and the utxos we must spend (this happens,
+            // for example, when we RBF)
+            // - We have a drain_to address and drain_wallet set
+            // Otherwise, we don't know who we should send the funds to, and how much
+            // we should send!
+            if params.drain_to.is_some() && (params.drain_wallet || !params.utxos.is_empty()) {
+                if let NoChange {
+                    dust_threshold,
+                    remaining_amount,
+                    change_fee,
+                } = excess
+                {
+                    return Err(CreateTxError::InsufficientFunds {
+                        needed: *dust_threshold,
+                        available: remaining_amount.saturating_sub(*change_fee),
+                    });
+                }
+            } else {
+                return Err(CreateTxError::NoRecipients);
+            }
+        }
+
+        match excess {
+            NoChange {
+                remaining_amount, ..
+            } => fee_amount += remaining_amount,
+            Change { amount, fee } => {
+                if self.is_mine(&drain_script) {
+                    received += amount;
+                }
+                fee_amount += fee;
+
+                // create drain output
+                let drain_output = TxOut {
+                    value: Amount::from_sat(*amount),
+                    script_pubkey: drain_script,
+                };
+
+                // TODO: We should pay attention when adding a new output: this might increase
+                // the length of the "number of vouts" parameter by 2 bytes, potentially making
+                // our feerate too low
+                tx.output.push(drain_output);
+            }
+        };
+
+        // sort input/outputs according to the chosen algorithm
+        params.ordering.sort_tx(&mut tx);
+
+        let psbt = self.complete_transaction(tx, coin_selection.selected, params)?;
+        Ok(psbt)
+    }
+
+    /// 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.
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # // TODO: remove norun -- bumping fee seems to need the tx in the wallet database first.
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk_wallet::*;
+    /// # use bdk_wallet::wallet::ChangeSet;
+    /// # use bdk_wallet::wallet::error::CreateTxError;
+    /// # use bdk_persist::PersistBackend;
+    /// # use anyhow::Error;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let mut wallet = doctest_wallet!();
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
+    /// let mut psbt = {
+    ///     let mut builder = wallet.build_tx();
+    ///     builder
+    ///         .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
+    ///         .enable_rbf();
+    ///     builder.finish()?
+    /// };
+    /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
+    /// let tx = psbt.clone().extract_tx().expect("tx");
+    /// // broadcast tx but it's taking too long to confirm so we want to bump the fee
+    /// let mut psbt =  {
+    ///     let mut builder = wallet.build_fee_bump(tx.txid())?;
+    ///     builder
+    ///         .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"));
+    ///     builder.finish()?
+    /// };
+    ///
+    /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
+    /// let fee_bumped_tx = psbt.extract_tx();
+    /// // broadcast fee_bumped_tx to replace original
+    /// # Ok::<(), anyhow::Error>(())
+    /// ```
+    // TODO: support for merging multiple transactions while bumping the fees
+    pub fn build_fee_bump(
+        &mut self,
+        txid: Txid,
+    ) -> Result<TxBuilder<'_, DefaultCoinSelectionAlgorithm, BumpFee>, BuildFeeBumpError> {
+        let graph = self.indexed_graph.graph();
+        let txout_index = &self.indexed_graph.index;
+        let chain_tip = self.chain.tip().block_id();
+
+        let mut tx = graph
+            .get_tx(txid)
+            .ok_or(BuildFeeBumpError::TransactionNotFound(txid))?
+            .as_ref()
+            .clone();
+
+        let pos = graph
+            .get_chain_position(&self.chain, chain_tip, txid)
+            .ok_or(BuildFeeBumpError::TransactionNotFound(txid))?;
+        if let ChainPosition::Confirmed(_) = pos {
+            return Err(BuildFeeBumpError::TransactionConfirmed(txid));
+        }
+
+        if !tx
+            .input
+            .iter()
+            .any(|txin| txin.sequence.to_consensus_u32() <= 0xFFFFFFFD)
+        {
+            return Err(BuildFeeBumpError::IrreplaceableTransaction(tx.txid()));
+        }
+
+        let fee = self
+            .calculate_fee(&tx)
+            .map_err(|_| BuildFeeBumpError::FeeRateUnavailable)?;
+        let fee_rate = self
+            .calculate_fee_rate(&tx)
+            .map_err(|_| BuildFeeBumpError::FeeRateUnavailable)?;
+
+        // 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<_, BuildFeeBumpError> {
+                let prev_tx = graph
+                    .get_tx(txin.previous_output.txid)
+                    .ok_or(BuildFeeBumpError::UnknownUtxo(txin.previous_output))?;
+                let txout = &prev_tx.output[txin.previous_output.vout as usize];
+
+                let confirmation_time: ConfirmationTime = graph
+                    .get_chain_position(&self.chain, chain_tip, txin.previous_output.txid)
+                    .ok_or(BuildFeeBumpError::UnknownUtxo(txin.previous_output))?
+                    .cloned()
+                    .into();
+
+                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_weight_to_satisfy()
+                            .unwrap();
+                        WeightedUtxo {
+                            utxo: Utxo::Local(LocalOutput {
+                                outpoint: txin.previous_output,
+                                txout: txout.clone(),
+                                keychain,
+                                is_spent: true,
+                                derivation_index,
+                                confirmation_time,
+                            }),
+                            satisfaction_weight,
+                        }
+                    }
+                    None => {
+                        let satisfaction_weight =
+                            serialize(&txin.script_sig).len() * 4 + serialize(&txin.witness).len();
+                        WeightedUtxo {
+                            utxo: Utxo::Foreign {
+                                outpoint: txin.previous_output,
+                                sequence: Some(txin.sequence),
+                                psbt_input: Box::new(psbt::Input {
+                                    witness_utxo: Some(txout.clone()),
+                                    non_witness_utxo: Some(prev_tx.as_ref().clone()),
+                                    ..Default::default()
+                                }),
+                            },
+                            satisfaction_weight,
+                        }
+                    }
+                };
+
+                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.map_keychain(KeychainKind::Internal);
+                match txout_index.index_of_spk(&txout.script_pubkey) {
+                    Some((keychain, _)) if keychain == change_type => change_index = Some(index),
+                    _ => {}
+                }
+            }
+
+            if let Some(change_index) = change_index {
+                tx.output.remove(change_index);
+            }
+        }
+
+        let params = TxParams {
+            // TODO: figure out what rbf option should be?
+            version: Some(tx_builder::Version(tx.version.0)),
+            recipients: tx
+                .output
+                .into_iter()
+                .map(|txout| (txout.script_pubkey, txout.value.to_sat()))
+                .collect(),
+            utxos: original_utxos,
+            bumping_fee: Some(tx_builder::PreviousFee {
+                absolute: fee,
+                rate: fee_rate,
+            }),
+            ..Default::default()
+        };
+
+        Ok(TxBuilder {
+            wallet: alloc::rc::Rc::new(core::cell::RefCell::new(self)),
+            params,
+            coin_selection: DefaultCoinSelectionAlgorithm::default(),
+            phantom: core::marker::PhantomData,
+        })
+    }
+
+    /// 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*
+    /// signers will follow the options, but the "software signers" (WIF keys and `xprv`) defined
+    /// in this library will.
+    ///
+    /// ## Example
+    ///
+    /// ```
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk_wallet::*;
+    /// # use bdk_wallet::wallet::ChangeSet;
+    /// # use bdk_wallet::wallet::error::CreateTxError;
+    /// # use bdk_persist::PersistBackend;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let mut wallet = doctest_wallet!();
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
+    /// let mut psbt = {
+    ///     let mut builder = wallet.build_tx();
+    ///     builder.add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000));
+    ///     builder.finish()?
+    /// };
+    /// let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
+    /// assert!(finalized, "we should have signed all the inputs");
+    /// # Ok::<(),anyhow::Error>(())
+    pub fn sign(&self, psbt: &mut Psbt, sign_options: SignOptions) -> Result<bool, SignerError> {
+        // This adds all the PSBT metadata for the inputs, which will help us later figure out how
+        // to derive our keys
+        self.update_psbt_with_descriptor(psbt)
+            .map_err(SignerError::MiniscriptPsbt)?;
+
+        // If we aren't allowed to use `witness_utxo`, ensure that every input (except p2tr and finalized ones)
+        // has the `non_witness_utxo`
+        if !sign_options.trust_witness_utxo
+            && psbt
+                .inputs
+                .iter()
+                .filter(|i| i.final_script_witness.is_none() && i.final_script_sig.is_none())
+                .filter(|i| i.tap_internal_key.is_none() && i.tap_merkle_root.is_none())
+                .any(|i| i.non_witness_utxo.is_none())
+        {
+            return Err(SignerError::MissingNonWitnessUtxo);
+        }
+
+        // If the user hasn't explicitly opted-in, refuse to sign the transaction unless every input
+        // is using `SIGHASH_ALL` or `SIGHASH_DEFAULT` for taproot
+        if !sign_options.allow_all_sighashes
+            && !psbt.inputs.iter().all(|i| {
+                i.sighash_type.is_none()
+                    || i.sighash_type == Some(EcdsaSighashType::All.into())
+                    || i.sighash_type == Some(TapSighashType::All.into())
+                    || i.sighash_type == Some(TapSighashType::Default.into())
+            })
+        {
+            return Err(SignerError::NonStandardSighash);
+        }
+
+        for signer in self
+            .signers
+            .signers()
+            .iter()
+            .chain(self.change_signers.signers().iter())
+        {
+            signer.sign_transaction(psbt, &sign_options, &self.secp)?;
+        }
+
+        // attempt to finalize
+        if sign_options.try_finalize {
+            self.finalize_psbt(psbt, sign_options)
+        } else {
+            Ok(false)
+        }
+    }
+
+    /// Return the spending policies for the wallet's descriptor
+    pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, DescriptorError> {
+        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),
+        }
+    }
+
+    /// 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
+    pub fn public_descriptor(&self, keychain: KeychainKind) -> Option<&ExtendedDescriptor> {
+        self.indexed_graph
+            .index
+            .keychains()
+            .find(|(k, _)| *k == &keychain)
+            .map(|(_, d)| d)
+    }
+
+    /// 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](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#Input_Finalizer)
+    /// 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.
+    pub fn finalize_psbt(
+        &self,
+        psbt: &mut Psbt,
+        sign_options: SignOptions,
+    ) -> Result<bool, SignerError> {
+        let chain_tip = self.chain.tip().block_id();
+
+        let tx = &psbt.unsigned_tx;
+        let mut finished = true;
+
+        for (n, input) in tx.input.iter().enumerate() {
+            let psbt_input = &psbt
+                .inputs
+                .get(n)
+                .ok_or(SignerError::InputIndexOutOfRange)?;
+            if psbt_input.final_script_sig.is_some() || psbt_input.final_script_witness.is_some() {
+                continue;
+            }
+            let confirmation_height = self
+                .indexed_graph
+                .graph()
+                .get_chain_position(&self.chain, chain_tip, input.previous_output.txid)
+                .map(|chain_position| match chain_position {
+                    ChainPosition::Confirmed(a) => a.confirmation_height,
+                    ChainPosition::Unconfirmed(_) => u32::MAX,
+                });
+            let current_height = sign_options
+                .assume_height
+                .unwrap_or_else(|| self.chain.tip().height());
+
+            // - Try to derive the descriptor by looking at the txout. If it's in our database, we
+            //   know exactly which `keychain` to use, and which derivation index it is
+            // - If that fails, try to derive it by looking at the psbt input: the complete logic
+            //   is in `src/descriptor/mod.rs`, but it will basically look at `bip32_derivation`,
+            //   `redeem_script` and `witness_script` to determine the right derivation
+            // - If that also fails, it will try it on the internal descriptor, if present
+            let desc = psbt
+                .get_utxo_for(n)
+                .and_then(|txout| self.get_descriptor_for_txout(&txout))
+                .or_else(|| {
+                    self.indexed_graph.index.keychains().find_map(|(_, desc)| {
+                        desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n), &self.secp)
+                    })
+                });
+
+            match desc {
+                Some(desc) => {
+                    let mut tmp_input = bitcoin::TxIn::default();
+                    match desc.satisfy(
+                        &mut tmp_input,
+                        (
+                            PsbtInputSatisfier::new(psbt, n),
+                            After::new(Some(current_height), false),
+                            Older::new(Some(current_height), confirmation_height, false),
+                        ),
+                    ) {
+                        Ok(_) => {
+                            let psbt_input = &mut psbt.inputs[n];
+                            psbt_input.final_script_sig = Some(tmp_input.script_sig);
+                            psbt_input.final_script_witness = Some(tmp_input.witness);
+                            if sign_options.remove_partial_sigs {
+                                psbt_input.partial_sigs.clear();
+                            }
+                            if sign_options.remove_taproot_extras {
+                                // We just constructed the final witness, clear these fields.
+                                psbt_input.tap_key_sig = None;
+                                psbt_input.tap_script_sigs.clear();
+                                psbt_input.tap_scripts.clear();
+                                psbt_input.tap_key_origins.clear();
+                                psbt_input.tap_internal_key = None;
+                                psbt_input.tap_merkle_root = None;
+                            }
+                        }
+                        Err(_) => finished = false,
+                    }
+                }
+                None => finished = false,
+            }
+        }
+
+        if finished && sign_options.remove_taproot_extras {
+            for output in &mut psbt.outputs {
+                output.tap_key_origins.clear();
+            }
+        }
+
+        Ok(finished)
+    }
+
+    /// Return the secp256k1 context used for all signing operations
+    pub fn secp_ctx(&self) -> &SecpCtx {
+        &self.secp
+    }
+
+    /// Returns the descriptor used to create addresses for a particular `keychain`.
+    pub fn get_descriptor_for_keychain(&self, keychain: KeychainKind) -> &ExtendedDescriptor {
+        self.public_descriptor(self.map_keychain(keychain))
+            .expect("we mapped it to external if it doesn't exist")
+    }
+
+    /// 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.indexed_graph.index.last_revealed_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 {
+        let keychain = self.map_keychain(keychain);
+        self.indexed_graph
+            .index
+            .next_index(&keychain)
+            .expect("Keychain must exist (we called map_keychain)")
+            .0
+    }
+
+    /// 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.indexed_graph.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);
+            }
+        }
+    }
+
+    fn map_keychain(&self, keychain: KeychainKind) -> KeychainKind {
+        if keychain == KeychainKind::Internal
+            && self.public_descriptor(KeychainKind::Internal).is_none()
+        {
+            KeychainKind::External
+        } else {
+            keychain
+        }
+    }
+
+    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Option<DerivedDescriptor> {
+        let (keychain, child) = self
+            .indexed_graph
+            .index
+            .index_of_spk(&txout.script_pubkey)?;
+        let descriptor = self.get_descriptor_for_keychain(keychain);
+        descriptor.at_derivation_index(child).ok()
+    }
+
+    fn get_available_utxos(&self) -> Vec<(LocalOutput, usize)> {
+        self.list_unspent()
+            .map(|utxo| {
+                let keychain = utxo.keychain;
+                (utxo, {
+                    self.get_descriptor_for_keychain(keychain)
+                        .max_weight_to_satisfy()
+                        .unwrap()
+                })
+            })
+            .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.
+    fn preselect_utxos(
+        &self,
+        params: &TxParams,
+        current_height: Option<u32>,
+    ) -> (Vec<WeightedUtxo>, Vec<WeightedUtxo>) {
+        let TxParams {
+            change_policy,
+            unspendable,
+            utxos,
+            drain_wallet,
+            manually_selected_only,
+            bumping_fee,
+            ..
+        } = params;
+
+        let manually_selected = utxos.clone();
+        // we mandate confirmed transactions if we're bumping the fee
+        let must_only_use_confirmed_tx = bumping_fee.is_some();
+        let must_use_all_available = *drain_wallet;
+
+        let chain_tip = self.chain.tip().block_id();
+        //    must_spend <- manually selected utxos
+        //    may_spend  <- all other available utxos
+        let mut may_spend = self.get_available_utxos();
+
+        may_spend.retain(|may_spend| {
+            !manually_selected
+                .iter()
+                .any(|manually_selected| manually_selected.utxo.outpoint() == may_spend.0.outpoint)
+        });
+        let mut must_spend = manually_selected;
+
+        // NOTE: we are intentionally ignoring `unspendable` here. i.e manual
+        // selection overrides unspendable.
+        if *manually_selected_only {
+            return (must_spend, vec![]);
+        }
+
+        let satisfies_confirmed = may_spend
+            .iter()
+            .map(|u| -> bool {
+                let txid = u.0.outpoint.txid;
+                let tx = match self.indexed_graph.graph().get_tx(txid) {
+                    Some(tx) => tx,
+                    None => return false,
+                };
+                let confirmation_time: ConfirmationTime = match self
+                    .indexed_graph
+                    .graph()
+                    .get_chain_position(&self.chain, chain_tip, txid)
+                {
+                    Some(chain_position) => chain_position.cloned().into(),
+                    None => return false,
+                };
+
+                // 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_coinbase() {
+                    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
+            })
+            .collect::<Vec<_>>();
+
+        let mut i = 0;
+        may_spend.retain(|u| {
+            let retain = change_policy.is_satisfied_by(&u.0)
+                && !unspendable.contains(&u.0.outpoint)
+                && satisfies_confirmed[i];
+            i += 1;
+            retain
+        });
+
+        let mut may_spend = may_spend
+            .into_iter()
+            .map(|(local_utxo, satisfaction_weight)| WeightedUtxo {
+                satisfaction_weight,
+                utxo: Utxo::Local(local_utxo),
+            })
+            .collect();
+
+        if must_use_all_available {
+            must_spend.append(&mut may_spend);
+        }
+
+        (must_spend, may_spend)
+    }
+
+    fn complete_transaction(
+        &self,
+        tx: Transaction,
+        selected: Vec<Utxo>,
+        params: TxParams,
+    ) -> Result<Psbt, CreateTxError> {
+        let mut psbt = Psbt::from_unsigned_tx(tx)?;
+
+        if params.add_global_xpubs {
+            let all_xpubs = self
+                .keychains()
+                .flat_map(|(_, desc)| desc.get_extended_keys())
+                .collect::<Vec<_>>();
+
+            for xpub in all_xpubs {
+                let origin = match xpub.origin {
+                    Some(origin) => origin,
+                    None if xpub.xkey.depth == 0 => {
+                        (xpub.root_fingerprint(&self.secp), vec![].into())
+                    }
+                    _ => return Err(CreateTxError::MissingKeyOrigin(xpub.xkey.to_string())),
+                };
+
+                psbt.xpub.insert(xpub.xkey, origin);
+            }
+        }
+
+        let mut lookup_output = selected
+            .into_iter()
+            .map(|utxo| (utxo.outpoint(), utxo))
+            .collect::<HashMap<_, _>>();
+
+        // add metadata for the inputs
+        for (psbt_input, input) in psbt.inputs.iter_mut().zip(psbt.unsigned_tx.input.iter()) {
+            let utxo = match lookup_output.remove(&input.previous_output) {
+                Some(utxo) => utxo,
+                None => continue,
+            };
+
+            match utxo {
+                Utxo::Local(utxo) => {
+                    *psbt_input =
+                        match self.get_psbt_input(utxo, params.sighash, params.only_witness_utxo) {
+                            Ok(psbt_input) => psbt_input,
+                            Err(e) => match e {
+                                CreateTxError::UnknownUtxo => psbt::Input {
+                                    sighash_type: params.sighash,
+                                    ..psbt::Input::default()
+                                },
+                                _ => return Err(e),
+                            },
+                        }
+                }
+                Utxo::Foreign {
+                    outpoint,
+                    psbt_input: foreign_psbt_input,
+                    ..
+                } => {
+                    let is_taproot = foreign_psbt_input
+                        .witness_utxo
+                        .as_ref()
+                        .map(|txout| txout.script_pubkey.is_p2tr())
+                        .unwrap_or(false);
+                    if !is_taproot
+                        && !params.only_witness_utxo
+                        && foreign_psbt_input.non_witness_utxo.is_none()
+                    {
+                        return Err(CreateTxError::MissingNonWitnessUtxo(outpoint));
+                    }
+                    *psbt_input = *foreign_psbt_input;
+                }
+            }
+        }
+
+        self.update_psbt_with_descriptor(&mut psbt)?;
+
+        Ok(psbt)
+    }
+
+    /// get the corresponding PSBT Input for a LocalUtxo
+    pub fn get_psbt_input(
+        &self,
+        utxo: LocalOutput,
+        sighash_type: Option<psbt::PsbtSighashType>,
+        only_witness_utxo: bool,
+    ) -> Result<psbt::Input, CreateTxError> {
+        // 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
+            .indexed_graph
+            .index
+            .index_of_spk(&utxo.txout.script_pubkey)
+            .ok_or(CreateTxError::UnknownUtxo)?;
+
+        let mut psbt_input = psbt::Input {
+            sighash_type,
+            ..psbt::Input::default()
+        };
+
+        let desc = self.get_descriptor_for_keychain(keychain);
+        let derived_descriptor = desc
+            .at_derivation_index(child)
+            .expect("child can't be hardened");
+
+        psbt_input
+            .update_with_descriptor_unchecked(&derived_descriptor)
+            .map_err(MiniscriptPsbtError::Conversion)?;
+
+        let prev_output = utxo.outpoint;
+        if let Some(prev_tx) = self.indexed_graph.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.as_ref().clone());
+            }
+        }
+        Ok(psbt_input)
+    }
+
+    fn update_psbt_with_descriptor(&self, psbt: &mut Psbt) -> Result<(), MiniscriptPsbtError> {
+        // We need to borrow `psbt` mutably within the loops, so we have to allocate a vec for all
+        // the input utxos and outputs
+        let utxos = (0..psbt.inputs.len())
+            .filter_map(|i| psbt.get_utxo_for(i).map(|utxo| (true, i, utxo)))
+            .chain(
+                psbt.unsigned_tx
+                    .output
+                    .iter()
+                    .enumerate()
+                    .map(|(i, out)| (false, i, out.clone())),
+            )
+            .collect::<Vec<_>>();
+
+        // 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.indexed_graph.index.index_of_spk(&out.script_pubkey)
+            {
+                let desc = self.get_descriptor_for_keychain(keychain);
+                let desc = desc
+                    .at_derivation_index(child)
+                    .expect("child can't be hardened");
+
+                if is_input {
+                    psbt.update_input_with_descriptor(index, &desc)
+                        .map_err(MiniscriptPsbtError::UtxoUpdate)?;
+                } else {
+                    psbt.update_output_with_descriptor(index, &desc)
+                        .map_err(MiniscriptPsbtError::OutputUpdate)?;
+                }
+            }
+        }
+
+        Ok(())
+    }
+
+    /// Return the checksum of the public descriptor associated to `keychain`
+    ///
+    /// Internally calls [`Self::get_descriptor_for_keychain`] to fetch the right descriptor
+    pub fn descriptor_checksum(&self, keychain: KeychainKind) -> String {
+        self.get_descriptor_for_keychain(keychain)
+            .to_string()
+            .split_once('#')
+            .unwrap()
+            .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: impl Into<Update>) -> Result<(), CannotConnectError> {
+        let update = update.into();
+        let mut changeset = match update.chain {
+            Some(chain_update) => ChangeSet::from(self.chain.apply_update(chain_update)?),
+            None => ChangeSet::default(),
+        };
+
+        let (_, index_changeset) = self
+            .indexed_graph
+            .index
+            .reveal_to_target_multi(&update.last_active_indices);
+        changeset.append(ChangeSet::from(indexed_tx_graph::ChangeSet::from(
+            index_changeset,
+        )));
+        changeset.append(ChangeSet::from(
+            self.indexed_graph.apply_update(update.graph),
+        ));
+        self.persist.stage(changeset);
+        Ok(())
+    }
+
+    /// Commits all currently [`staged`] changed to the persistence backend returning and error when
+    /// this fails.
+    ///
+    /// This returns whether the `update` resulted in any changes.
+    ///
+    /// [`staged`]: Self::staged
+    pub fn commit(&mut self) -> anyhow::Result<bool> {
+        self.persist.commit().map(|c| c.is_some())
+    }
+
+    /// Returns the changes that will be committed with the next call to [`commit`].
+    ///
+    /// [`commit`]: Self::commit
+    pub fn staged(&self) -> &ChangeSet {
+        self.persist.staged()
+    }
+
+    /// Get a reference to the inner [`TxGraph`].
+    pub fn tx_graph(&self) -> &TxGraph<ConfirmationTimeHeightAnchor> {
+        self.indexed_graph.graph()
+    }
+
+    /// Get a reference to the inner [`KeychainTxOutIndex`].
+    pub fn spk_index(&self) -> &KeychainTxOutIndex<KeychainKind> {
+        &self.indexed_graph.index
+    }
+
+    /// Get a reference to the inner [`LocalChain`].
+    pub fn local_chain(&self) -> &LocalChain {
+        &self.chain
+    }
+
+    /// Introduces a `block` of `height` to the wallet, and tries to connect it to the
+    /// `prev_blockhash` of the block's header.
+    ///
+    /// This is a convenience method that is equivalent to calling [`apply_block_connected_to`]
+    /// with `prev_blockhash` and `height-1` as the `connected_to` parameter.
+    ///
+    /// [`apply_block_connected_to`]: Self::apply_block_connected_to
+    pub fn apply_block(&mut self, block: &Block, height: u32) -> Result<(), CannotConnectError> {
+        let connected_to = match height.checked_sub(1) {
+            Some(prev_height) => BlockId {
+                height: prev_height,
+                hash: block.header.prev_blockhash,
+            },
+            None => BlockId {
+                height,
+                hash: block.block_hash(),
+            },
+        };
+        self.apply_block_connected_to(block, height, connected_to)
+            .map_err(|err| match err {
+                ApplyHeaderError::InconsistentBlocks => {
+                    unreachable!("connected_to is derived from the block so must be consistent")
+                }
+                ApplyHeaderError::CannotConnect(err) => err,
+            })
+    }
+
+    /// Applies relevant transactions from `block` of `height` to the wallet, and connects the
+    /// block to the internal chain.
+    ///
+    /// The `connected_to` parameter informs the wallet how this block connects to the internal
+    /// [`LocalChain`]. Relevant transactions are filtered from the `block` and inserted into the
+    /// internal [`TxGraph`].
+    pub fn apply_block_connected_to(
+        &mut self,
+        block: &Block,
+        height: u32,
+        connected_to: BlockId,
+    ) -> Result<(), ApplyHeaderError> {
+        let mut changeset = ChangeSet::default();
+        changeset.append(
+            self.chain
+                .apply_header_connected_to(&block.header, height, connected_to)?
+                .into(),
+        );
+        changeset.append(
+            self.indexed_graph
+                .apply_block_relevant(block, height)
+                .into(),
+        );
+        self.persist.stage(changeset);
+        Ok(())
+    }
+
+    /// Apply relevant unconfirmed transactions to the wallet.
+    ///
+    /// Transactions that are not relevant are filtered out.
+    ///
+    /// This method takes in an iterator of `(tx, last_seen)` where `last_seen` is the timestamp of
+    /// when the transaction was last seen in the mempool. This is used for conflict resolution
+    /// when there is conflicting unconfirmed transactions. The transaction with the later
+    /// `last_seen` is prioritized.
+    pub fn apply_unconfirmed_txs<'t>(
+        &mut self,
+        unconfirmed_txs: impl IntoIterator<Item = (&'t Transaction, u64)>,
+    ) {
+        let indexed_graph_changeset = self
+            .indexed_graph
+            .batch_insert_relevant_unconfirmed(unconfirmed_txs);
+        self.persist.stage(ChangeSet::from(indexed_graph_changeset));
+    }
+}
+
+/// Methods to construct sync/full-scan requests for spk-based chain sources.
+impl Wallet {
+    /// Create a partial [`SyncRequest`] for this wallet for all revealed spks.
+    ///
+    /// This is the first step when performing a spk-based wallet partial sync, the returned
+    /// [`SyncRequest`] collects all revealed script pubkeys from the wallet keychain needed to
+    /// start a blockchain sync with a spk based blockchain client.
+    pub fn start_sync_with_revealed_spks(&self) -> SyncRequest {
+        SyncRequest::from_chain_tip(self.chain.tip())
+            .cache_graph_txs(self.tx_graph())
+            .populate_with_revealed_spks(&self.indexed_graph.index, ..)
+    }
+
+    /// Create a [`FullScanRequest] for this wallet.
+    ///
+    /// This is the first step when performing a spk-based wallet full scan, the returned
+    /// [`FullScanRequest] collects iterators for the wallet's keychain script pub keys needed to
+    /// start a blockchain full scan with a spk based blockchain client.
+    ///
+    /// This operation is generally only used when importing or restoring a previously used wallet
+    /// in which the list of used scripts is not known.
+    pub fn start_full_scan(&self) -> FullScanRequest<KeychainKind> {
+        FullScanRequest::from_keychain_txout_index(self.chain.tip(), &self.indexed_graph.index)
+            .cache_graph_txs(self.tx_graph())
+    }
+}
+
+impl AsRef<bdk_chain::tx_graph::TxGraph<ConfirmationTimeHeightAnchor>> for Wallet {
+    fn as_ref(&self) -> &bdk_chain::tx_graph::TxGraph<ConfirmationTimeHeightAnchor> {
+        self.indexed_graph.graph()
+    }
+}
+
+/// Deterministically generate a unique name given the descriptors defining the wallet
+///
+/// Compatible with [`wallet_name_from_descriptor`]
+pub fn wallet_name_from_descriptor<T>(
+    descriptor: T,
+    change_descriptor: Option<T>,
+    network: Network,
+    secp: &SecpCtx,
+) -> Result<String, DescriptorError>
+where
+    T: IntoWalletDescriptor,
+{
+    //TODO check descriptors contains only public keys
+    let descriptor = descriptor
+        .into_wallet_descriptor(secp, network)?
+        .0
+        .to_string();
+    let mut wallet_name = calc_checksum(&descriptor[..descriptor.find('#').unwrap()])?;
+    if let Some(change_descriptor) = change_descriptor {
+        let change_descriptor = change_descriptor
+            .into_wallet_descriptor(secp, network)?
+            .0
+            .to_string();
+        wallet_name.push_str(
+            calc_checksum(&change_descriptor[..change_descriptor.find('#').unwrap()])?.as_str(),
+        );
+    }
+
+    Ok(wallet_name)
+}
+
+fn new_local_utxo(
+    keychain: KeychainKind,
+    derivation_index: u32,
+    full_txo: FullTxOut<ConfirmationTimeHeightAnchor>,
+) -> LocalOutput {
+    LocalOutput {
+        outpoint: full_txo.outpoint,
+        txout: full_txo.txout,
+        is_spent: full_txo.spent_by.is_some(),
+        confirmation_time: full_txo.chain_position.into(),
+        keychain,
+        derivation_index,
+    }
+}
+
+fn create_signers<E: IntoWalletDescriptor>(
+    index: &mut KeychainTxOutIndex<KeychainKind>,
+    secp: &Secp256k1<All>,
+    descriptor: E,
+    change_descriptor: Option<E>,
+    network: Network,
+) -> Result<(Arc<SignersContainer>, Arc<SignersContainer>), crate::descriptor::error::Error> {
+    let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, secp, network)?;
+    let signers = Arc::new(SignersContainer::build(keymap, &descriptor, secp));
+    let _ = index.insert_descriptor(KeychainKind::External, descriptor);
+
+    let change_signers = match change_descriptor {
+        Some(descriptor) => {
+            let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, secp, network)?;
+            let signers = Arc::new(SignersContainer::build(keymap, &descriptor, secp));
+            let _ = index.insert_descriptor(KeychainKind::Internal, descriptor);
+            signers
+        }
+        None => Arc::new(SignersContainer::new()),
+    };
+
+    Ok((signers, change_signers))
+}
+
+/// Transforms a [`FeeRate`] to `f64` with unit as sat/vb.
+#[macro_export]
+#[doc(hidden)]
+macro_rules! floating_rate {
+    ($rate:expr) => {{
+        use $crate::bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
+        // sat_kwu / 250.0 -> sat_vb
+        $rate.to_sat_per_kwu() as f64 / ((1000 / WITNESS_SCALE_FACTOR) as f64)
+    }};
+}
+
+#[macro_export]
+#[doc(hidden)]
+/// Macro for getting a wallet for use in a doctest
+macro_rules! doctest_wallet {
+    () => {{
+        use $crate::bitcoin::{BlockHash, Transaction, absolute, TxOut, Network, hashes::Hash};
+        use $crate::chain::{ConfirmationTime, BlockId};
+        use $crate::{KeychainKind, wallet::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,
+        )
+        .unwrap();
+        let address = wallet.peek_address(KeychainKind::External, 0).address;
+        let tx = Transaction {
+            version: transaction::Version::ONE,
+            lock_time: absolute::LockTime::ZERO,
+            input: vec![],
+            output: vec![TxOut {
+                value: Amount::from_sat(500_000),
+                script_pubkey: address.script_pubkey(),
+            }],
+        };
+        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
+        });
+
+        wallet
+    }}
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/signer.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/signer.rs.html new file mode 100644 index 0000000000..b3dae865e4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/signer.rs.html @@ -0,0 +1,2389 @@ +signer.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
+1148
+1149
+1150
+1151
+1152
+1153
+1154
+1155
+1156
+1157
+1158
+1159
+1160
+1161
+1162
+1163
+1164
+1165
+1166
+1167
+1168
+1169
+1170
+1171
+1172
+1173
+1174
+1175
+1176
+1177
+1178
+1179
+1180
+1181
+1182
+1183
+1184
+1185
+1186
+1187
+1188
+1189
+1190
+1191
+1192
+1193
+
// 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.
+
+//! Generalized signers
+//!
+//! This module provides the ability to add customized signers to a [`Wallet`](super::Wallet)
+//! through the [`Wallet::add_signer`](super::Wallet::add_signer) function.
+//!
+//! ```
+//! # use alloc::sync::Arc;
+//! # use core::str::FromStr;
+//! # use bitcoin::secp256k1::{Secp256k1, All};
+//! # use bitcoin::*;
+//! # use bdk_wallet::signer::*;
+//! # use bdk_wallet::*;
+//! # #[derive(Debug)]
+//! # struct CustomHSM;
+//! # impl CustomHSM {
+//! #     fn hsm_sign_input(&self, _psbt: &mut Psbt, _input: usize) -> Result<(), SignerError> {
+//! #         Ok(())
+//! #     }
+//! #     fn connect() -> Self {
+//! #         CustomHSM
+//! #     }
+//! #     fn get_id(&self) -> SignerId {
+//! #         SignerId::Dummy(0)
+//! #     }
+//! # }
+//! #[derive(Debug)]
+//! struct CustomSigner {
+//!     device: CustomHSM,
+//! }
+//!
+//! impl CustomSigner {
+//!     fn connect() -> Self {
+//!         CustomSigner { device: CustomHSM::connect() }
+//!     }
+//! }
+//!
+//! impl SignerCommon for CustomSigner {
+//!     fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
+//!         self.device.get_id()
+//!     }
+//! }
+//!
+//! impl InputSigner for CustomSigner {
+//!     fn sign_input(
+//!         &self,
+//!         psbt: &mut Psbt,
+//!         input_index: usize,
+//!         _sign_options: &SignOptions,
+//!         _secp: &Secp256k1<All>,
+//!     ) -> Result<(), SignerError> {
+//!         self.device.hsm_sign_input(psbt, input_index)?;
+//!
+//!         Ok(())
+//!     }
+//! }
+//!
+//! let custom_signer = CustomSigner::connect();
+//!
+//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+//! let mut wallet = Wallet::new_no_persist(descriptor, None, Network::Testnet)?;
+//! wallet.add_signer(
+//!     KeychainKind::External,
+//!     SignerOrdering(200),
+//!     Arc::new(custom_signer)
+//! );
+//!
+//! # Ok::<_, anyhow::Error>(())
+//! ```
+
+use crate::collections::BTreeMap;
+use alloc::string::String;
+use alloc::sync::Arc;
+use alloc::vec::Vec;
+use core::cmp::Ordering;
+use core::fmt;
+use core::ops::{Bound::Included, Deref};
+
+use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpriv};
+use bitcoin::hashes::hash160;
+use bitcoin::secp256k1::Message;
+use bitcoin::sighash::{EcdsaSighashType, TapSighash, TapSighashType};
+use bitcoin::{ecdsa, psbt, sighash, taproot};
+use bitcoin::{key::TapTweak, key::XOnlyPublicKey, secp256k1};
+use bitcoin::{PrivateKey, Psbt, PublicKey};
+
+use miniscript::descriptor::{
+    Descriptor, DescriptorMultiXKey, DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey,
+    InnerXKey, KeyMap, SinglePriv, SinglePubKey,
+};
+use miniscript::{Legacy, Segwitv0, SigType, Tap, ToPublicKey};
+
+use super::utils::SecpCtx;
+use crate::descriptor::{DescriptorMeta, XKeyUtils};
+use crate::psbt::PsbtUtils;
+use crate::wallet::error::MiniscriptPsbtError;
+
+/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
+/// multiple of them
+#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq, Hash)]
+pub enum SignerId {
+    /// Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA public key
+    PkHash(hash160::Hash),
+    /// The fingerprint of a BIP32 extended key
+    Fingerprint(Fingerprint),
+    /// Dummy identifier
+    Dummy(u64),
+}
+
+impl From<hash160::Hash> for SignerId {
+    fn from(hash: hash160::Hash) -> SignerId {
+        SignerId::PkHash(hash)
+    }
+}
+
+impl From<Fingerprint> for SignerId {
+    fn from(fing: Fingerprint) -> SignerId {
+        SignerId::Fingerprint(fing)
+    }
+}
+
+/// Signing error
+#[derive(Debug)]
+pub enum SignerError {
+    /// The private key is missing for the required public key
+    MissingKey,
+    /// The private key in use has the right fingerprint but derives differently than expected
+    InvalidKey,
+    /// The user canceled the operation
+    UserCanceled,
+    /// Input index is out of range
+    InputIndexOutOfRange,
+    /// The `non_witness_utxo` field of the transaction is required to sign this input
+    MissingNonWitnessUtxo,
+    /// The `non_witness_utxo` specified is invalid
+    InvalidNonWitnessUtxo,
+    /// The `witness_utxo` field of the transaction is required to sign this input
+    MissingWitnessUtxo,
+    /// The `witness_script` field of the transaction is required to sign this input
+    MissingWitnessScript,
+    /// The fingerprint and derivation path are missing from the psbt input
+    MissingHdKeypath,
+    /// The psbt contains a non-`SIGHASH_ALL` sighash in one of its input and the user hasn't
+    /// explicitly allowed them
+    ///
+    /// To enable signing transactions with non-standard sighashes set
+    /// [`SignOptions::allow_all_sighashes`] to `true`.
+    NonStandardSighash,
+    /// Invalid SIGHASH for the signing context in use
+    InvalidSighash,
+    /// Error while computing the hash to sign
+    SighashError(sighash::Error),
+    /// Miniscript PSBT error
+    MiniscriptPsbt(MiniscriptPsbtError),
+    /// To be used only by external libraries implementing [`InputSigner`] or
+    /// [`TransactionSigner`], so that they can return their own custom errors, without having to
+    /// modify [`SignerError`] in BDK.
+    External(String),
+}
+
+impl From<sighash::Error> for SignerError {
+    fn from(e: sighash::Error) -> Self {
+        SignerError::SighashError(e)
+    }
+}
+
+impl fmt::Display for SignerError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::MissingKey => write!(f, "Missing private key"),
+            Self::InvalidKey => write!(f, "The private key in use has the right fingerprint but derives differently than expected"),
+            Self::UserCanceled => write!(f, "The user canceled the operation"),
+            Self::InputIndexOutOfRange => write!(f, "Input index out of range"),
+            Self::MissingNonWitnessUtxo => write!(f, "Missing non-witness UTXO"),
+            Self::InvalidNonWitnessUtxo => write!(f, "Invalid non-witness UTXO"),
+            Self::MissingWitnessUtxo => write!(f, "Missing witness UTXO"),
+            Self::MissingWitnessScript => write!(f, "Missing witness script"),
+            Self::MissingHdKeypath => write!(f, "Missing fingerprint and derivation path"),
+            Self::NonStandardSighash => write!(f, "The psbt contains a non standard sighash"),
+            Self::InvalidSighash => write!(f, "Invalid SIGHASH for the signing context in use"),
+            Self::SighashError(err) => write!(f, "Error while computing the hash to sign: {}", err),
+            Self::MiniscriptPsbt(err) => write!(f, "Miniscript PSBT error: {}", err),
+            Self::External(err) => write!(f, "{}", err),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for SignerError {}
+
+/// Signing context
+///
+/// Used by our software signers to determine the type of signatures to make
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum SignerContext {
+    /// Legacy context
+    Legacy,
+    /// Segwit v0 context (BIP 143)
+    Segwitv0,
+    /// Taproot context (BIP 340)
+    Tap {
+        /// Whether the signer can sign for the internal key or not
+        is_internal_key: bool,
+    },
+}
+
+/// Wrapper to pair a signer with its context
+#[derive(Debug, Clone)]
+pub struct SignerWrapper<S: Sized + fmt::Debug + Clone> {
+    signer: S,
+    ctx: SignerContext,
+}
+
+impl<S: Sized + fmt::Debug + Clone> SignerWrapper<S> {
+    /// Create a wrapped signer from a signer and a context
+    pub fn new(signer: S, ctx: SignerContext) -> Self {
+        SignerWrapper { signer, ctx }
+    }
+}
+
+impl<S: Sized + fmt::Debug + Clone> Deref for SignerWrapper<S> {
+    type Target = S;
+
+    fn deref(&self) -> &Self::Target {
+        &self.signer
+    }
+}
+
+/// Common signer methods
+pub trait SignerCommon: fmt::Debug + Send + Sync {
+    /// Return the [`SignerId`] for this signer
+    ///
+    /// The [`SignerId`] can be used to lookup a signer in the [`Wallet`](crate::Wallet)'s signers map or to
+    /// compare two signers.
+    fn id(&self, secp: &SecpCtx) -> SignerId;
+
+    /// 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).
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        None
+    }
+}
+
+/// 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`].
+pub trait InputSigner: SignerCommon {
+    /// Sign a single psbt input
+    fn sign_input(
+        &self,
+        psbt: &mut Psbt,
+        input_index: usize,
+        sign_options: &SignOptions,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError>;
+}
+
+/// PSBT signer
+///
+/// This trait can be implemented when the signer can't sign inputs individually, but signs the whole transaction
+/// at once.
+pub trait TransactionSigner: SignerCommon {
+    /// Sign all the inputs of the psbt
+    fn sign_transaction(
+        &self,
+        psbt: &mut Psbt,
+        sign_options: &SignOptions,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError>;
+}
+
+impl<T: InputSigner> TransactionSigner for T {
+    fn sign_transaction(
+        &self,
+        psbt: &mut Psbt,
+        sign_options: &SignOptions,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError> {
+        for input_index in 0..psbt.inputs.len() {
+            self.sign_input(psbt, input_index, sign_options, secp)?;
+        }
+
+        Ok(())
+    }
+}
+
+impl SignerCommon for SignerWrapper<DescriptorXKey<Xpriv>> {
+    fn id(&self, secp: &SecpCtx) -> SignerId {
+        SignerId::from(self.root_fingerprint(secp))
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::XPrv(self.signer.clone()))
+    }
+}
+
+impl InputSigner for SignerWrapper<DescriptorXKey<Xpriv>> {
+    fn sign_input(
+        &self,
+        psbt: &mut Psbt,
+        input_index: usize,
+        sign_options: &SignOptions,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError> {
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        if psbt.inputs[input_index].final_script_sig.is_some()
+            || psbt.inputs[input_index].final_script_witness.is_some()
+        {
+            return Ok(());
+        }
+
+        let tap_key_origins = psbt.inputs[input_index]
+            .tap_key_origins
+            .iter()
+            .map(|(pk, (_, keysource))| (SinglePubKey::XOnly(*pk), keysource));
+        let (public_key, full_path) = match psbt.inputs[input_index]
+            .bip32_derivation
+            .iter()
+            .map(|(pk, keysource)| (SinglePubKey::FullKey(PublicKey::new(*pk)), keysource))
+            .chain(tap_key_origins)
+            .find_map(|(pk, keysource)| {
+                if self.matches(keysource, secp).is_some() {
+                    Some((pk, keysource.1.clone()))
+                } else {
+                    None
+                }
+            }) {
+            Some((pk, full_path)) => (pk, full_path),
+            None => return Ok(()),
+        };
+
+        let derived_key = match self.origin.clone() {
+            Some((_fingerprint, origin_path)) => {
+                let deriv_path = DerivationPath::from(
+                    &full_path.into_iter().cloned().collect::<Vec<ChildNumber>>()
+                        [origin_path.len()..],
+                );
+                self.xkey.derive_priv(secp, &deriv_path).unwrap()
+            }
+            None => self.xkey.derive_priv(secp, &full_path).unwrap(),
+        };
+
+        let computed_pk = secp256k1::PublicKey::from_secret_key(secp, &derived_key.private_key);
+        let valid_key = match public_key {
+            SinglePubKey::FullKey(pk) if pk.inner == computed_pk => true,
+            SinglePubKey::XOnly(x_only) if XOnlyPublicKey::from(computed_pk) == x_only => true,
+            _ => false,
+        };
+        if !valid_key {
+            Err(SignerError::InvalidKey)
+        } else {
+            // HD wallets imply compressed keys
+            let priv_key = PrivateKey {
+                compressed: true,
+                network: self.xkey.network,
+                inner: derived_key.private_key,
+            };
+
+            SignerWrapper::new(priv_key, self.ctx).sign_input(psbt, input_index, sign_options, secp)
+        }
+    }
+}
+
+fn multikey_to_xkeys<K: InnerXKey + Clone>(
+    multikey: DescriptorMultiXKey<K>,
+) -> Vec<DescriptorXKey<K>> {
+    multikey
+        .derivation_paths
+        .into_paths()
+        .into_iter()
+        .map(|derivation_path| DescriptorXKey {
+            origin: multikey.origin.clone(),
+            xkey: multikey.xkey.clone(),
+            derivation_path,
+            wildcard: multikey.wildcard,
+        })
+        .collect()
+}
+
+impl SignerCommon for SignerWrapper<DescriptorMultiXKey<Xpriv>> {
+    fn id(&self, secp: &SecpCtx) -> SignerId {
+        SignerId::from(self.root_fingerprint(secp))
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::MultiXPrv(self.signer.clone()))
+    }
+}
+
+impl InputSigner for SignerWrapper<DescriptorMultiXKey<Xpriv>> {
+    fn sign_input(
+        &self,
+        psbt: &mut Psbt,
+        input_index: usize,
+        sign_options: &SignOptions,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError> {
+        let xkeys = multikey_to_xkeys(self.signer.clone());
+        for xkey in xkeys {
+            SignerWrapper::new(xkey, self.ctx).sign_input(psbt, input_index, sign_options, secp)?
+        }
+        Ok(())
+    }
+}
+
+impl SignerCommon for SignerWrapper<PrivateKey> {
+    fn id(&self, secp: &SecpCtx) -> SignerId {
+        SignerId::from(self.public_key(secp).to_pubkeyhash(SigType::Ecdsa))
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::Single(SinglePriv {
+            key: self.signer,
+            origin: None,
+        }))
+    }
+}
+
+impl InputSigner for SignerWrapper<PrivateKey> {
+    fn sign_input(
+        &self,
+        psbt: &mut Psbt,
+        input_index: usize,
+        sign_options: &SignOptions,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError> {
+        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        if psbt.inputs[input_index].final_script_sig.is_some()
+            || psbt.inputs[input_index].final_script_witness.is_some()
+        {
+            return Ok(());
+        }
+
+        let pubkey = PublicKey::from_private_key(secp, self);
+        let x_only_pubkey = XOnlyPublicKey::from(pubkey.inner);
+
+        if let SignerContext::Tap { is_internal_key } = self.ctx {
+            if let Some(psbt_internal_key) = psbt.inputs[input_index].tap_internal_key {
+                if is_internal_key
+                    && psbt.inputs[input_index].tap_key_sig.is_none()
+                    && sign_options.sign_with_tap_internal_key
+                    && x_only_pubkey == psbt_internal_key
+                {
+                    let (hash, hash_ty) = Tap::sighash(psbt, input_index, None)?;
+                    sign_psbt_schnorr(
+                        &self.inner,
+                        x_only_pubkey,
+                        None,
+                        &mut psbt.inputs[input_index],
+                        hash,
+                        hash_ty,
+                        secp,
+                    );
+                }
+            }
+
+            if let Some((leaf_hashes, _)) =
+                psbt.inputs[input_index].tap_key_origins.get(&x_only_pubkey)
+            {
+                let leaf_hashes = leaf_hashes
+                    .iter()
+                    .filter(|lh| {
+                        // Removing the leaves we shouldn't sign for
+                        let should_sign = match &sign_options.tap_leaves_options {
+                            TapLeavesOptions::All => true,
+                            TapLeavesOptions::Include(v) => v.contains(lh),
+                            TapLeavesOptions::Exclude(v) => !v.contains(lh),
+                            TapLeavesOptions::None => false,
+                        };
+                        // Filtering out the leaves without our key
+                        should_sign
+                            && !psbt.inputs[input_index]
+                                .tap_script_sigs
+                                .contains_key(&(x_only_pubkey, **lh))
+                    })
+                    .cloned()
+                    .collect::<Vec<_>>();
+                for lh in leaf_hashes {
+                    let (hash, hash_ty) = Tap::sighash(psbt, input_index, Some(lh))?;
+                    sign_psbt_schnorr(
+                        &self.inner,
+                        x_only_pubkey,
+                        Some(lh),
+                        &mut psbt.inputs[input_index],
+                        hash,
+                        hash_ty,
+                        secp,
+                    );
+                }
+            }
+
+            return Ok(());
+        }
+
+        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
+            return Ok(());
+        }
+
+        let (hash, hash_ty) = match self.ctx {
+            SignerContext::Segwitv0 => {
+                let (h, t) = Segwitv0::sighash(psbt, input_index, ())?;
+                let h = h.to_raw_hash();
+                (h, t)
+            }
+            SignerContext::Legacy => {
+                let (h, t) = Legacy::sighash(psbt, input_index, ())?;
+                let h = h.to_raw_hash();
+                (h, t)
+            }
+            _ => return Ok(()), // handled above
+        };
+        sign_psbt_ecdsa(
+            &self.inner,
+            pubkey,
+            &mut psbt.inputs[input_index],
+            hash,
+            hash_ty,
+            secp,
+            sign_options.allow_grinding,
+        );
+
+        Ok(())
+    }
+}
+
+fn sign_psbt_ecdsa(
+    secret_key: &secp256k1::SecretKey,
+    pubkey: PublicKey,
+    psbt_input: &mut psbt::Input,
+    hash: impl bitcoin::hashes::Hash + bitcoin::secp256k1::ThirtyTwoByteHash,
+    hash_ty: EcdsaSighashType,
+    secp: &SecpCtx,
+    allow_grinding: bool,
+) {
+    let msg = &Message::from(hash);
+    let sig = if allow_grinding {
+        secp.sign_ecdsa_low_r(msg, secret_key)
+    } else {
+        secp.sign_ecdsa(msg, secret_key)
+    };
+    secp.verify_ecdsa(msg, &sig, &pubkey.inner)
+        .expect("invalid or corrupted ecdsa signature");
+
+    let final_signature = ecdsa::Signature { sig, hash_ty };
+    psbt_input.partial_sigs.insert(pubkey, final_signature);
+}
+
+// Calling this with `leaf_hash` = `None` will sign for key-spend
+fn sign_psbt_schnorr(
+    secret_key: &secp256k1::SecretKey,
+    pubkey: XOnlyPublicKey,
+    leaf_hash: Option<taproot::TapLeafHash>,
+    psbt_input: &mut psbt::Input,
+    hash: TapSighash,
+    hash_ty: TapSighashType,
+    secp: &SecpCtx,
+) {
+    let keypair = secp256k1::Keypair::from_seckey_slice(secp, secret_key.as_ref()).unwrap();
+    let keypair = match leaf_hash {
+        None => keypair
+            .tap_tweak(secp, psbt_input.tap_merkle_root)
+            .to_inner(),
+        Some(_) => keypair, // no tweak for script spend
+    };
+
+    let msg = &Message::from(hash);
+    let sig = secp.sign_schnorr(msg, &keypair);
+    secp.verify_schnorr(&sig, msg, &XOnlyPublicKey::from_keypair(&keypair).0)
+        .expect("invalid or corrupted schnorr signature");
+
+    let final_signature = taproot::Signature { sig, hash_ty };
+
+    if let Some(lh) = leaf_hash {
+        psbt_input
+            .tap_script_sigs
+            .insert((pubkey, lh), final_signature);
+    } else {
+        psbt_input.tap_key_sig = Some(final_signature);
+    }
+}
+
+/// 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.
+#[derive(Debug, Clone, PartialOrd, PartialEq, Ord, Eq)]
+pub struct SignerOrdering(pub usize);
+
+impl Default for SignerOrdering {
+    fn default() -> Self {
+        SignerOrdering(100)
+    }
+}
+
+#[derive(Debug, Clone)]
+struct SignersContainerKey {
+    id: SignerId,
+    ordering: SignerOrdering,
+}
+
+impl From<(SignerId, SignerOrdering)> for SignersContainerKey {
+    fn from(tuple: (SignerId, SignerOrdering)) -> Self {
+        SignersContainerKey {
+            id: tuple.0,
+            ordering: tuple.1,
+        }
+    }
+}
+
+/// Container for multiple signers
+#[derive(Debug, Default, Clone)]
+pub struct SignersContainer(BTreeMap<SignersContainerKey, Arc<dyn TransactionSigner>>);
+
+impl SignersContainer {
+    /// Create a map of public keys to secret keys
+    pub fn as_key_map(&self, secp: &SecpCtx) -> KeyMap {
+        self.0
+            .values()
+            .filter_map(|signer| signer.descriptor_secret_key())
+            .filter_map(|secret| secret.to_public(secp).ok().map(|public| (public, secret)))
+            .collect()
+    }
+
+    /// Build a new signer container from a [`KeyMap`]
+    ///
+    /// Also looks at the corresponding descriptor to determine the [`SignerContext`] to attach to
+    /// the signers
+    pub fn build(
+        keymap: KeyMap,
+        descriptor: &Descriptor<DescriptorPublicKey>,
+        secp: &SecpCtx,
+    ) -> SignersContainer {
+        let mut container = SignersContainer::new();
+
+        for (pubkey, secret) in keymap {
+            let ctx = match descriptor {
+                Descriptor::Tr(tr) => SignerContext::Tap {
+                    is_internal_key: tr.internal_key() == &pubkey,
+                },
+                _ if descriptor.is_witness() => SignerContext::Segwitv0,
+                _ => SignerContext::Legacy,
+            };
+
+            match secret {
+                DescriptorSecretKey::Single(private_key) => container.add_external(
+                    SignerId::from(
+                        private_key
+                            .key
+                            .public_key(secp)
+                            .to_pubkeyhash(SigType::Ecdsa),
+                    ),
+                    SignerOrdering::default(),
+                    Arc::new(SignerWrapper::new(private_key.key, ctx)),
+                ),
+                DescriptorSecretKey::XPrv(xprv) => container.add_external(
+                    SignerId::from(xprv.root_fingerprint(secp)),
+                    SignerOrdering::default(),
+                    Arc::new(SignerWrapper::new(xprv, ctx)),
+                ),
+                DescriptorSecretKey::MultiXPrv(xprv) => container.add_external(
+                    SignerId::from(xprv.root_fingerprint(secp)),
+                    SignerOrdering::default(),
+                    Arc::new(SignerWrapper::new(xprv, ctx)),
+                ),
+            };
+        }
+
+        container
+    }
+}
+
+impl SignersContainer {
+    /// Default constructor
+    pub fn new() -> Self {
+        SignersContainer(Default::default())
+    }
+
+    /// Adds an external signer to the container for the specified id. Optionally returns the
+    /// signer that was previously in the container, if any
+    pub fn add_external(
+        &mut self,
+        id: SignerId,
+        ordering: SignerOrdering,
+        signer: Arc<dyn TransactionSigner>,
+    ) -> Option<Arc<dyn TransactionSigner>> {
+        self.0.insert((id, ordering).into(), signer)
+    }
+
+    /// Removes a signer from the container and returns it
+    pub fn remove(
+        &mut self,
+        id: SignerId,
+        ordering: SignerOrdering,
+    ) -> Option<Arc<dyn TransactionSigner>> {
+        self.0.remove(&(id, ordering).into())
+    }
+
+    /// Returns the list of identifiers of all the signers in the container
+    pub fn ids(&self) -> Vec<&SignerId> {
+        self.0
+            .keys()
+            .map(|SignersContainerKey { id, .. }| id)
+            .collect()
+    }
+
+    /// Returns the list of signers in the container, sorted by lowest to highest `ordering`
+    pub fn signers(&self) -> Vec<&Arc<dyn TransactionSigner>> {
+        self.0.values().collect()
+    }
+
+    /// Finds the signer with lowest ordering for a given id in the container.
+    pub fn find(&self, id: SignerId) -> Option<&Arc<dyn TransactionSigner>> {
+        self.0
+            .range((
+                Included(&(id.clone(), SignerOrdering(0)).into()),
+                Included(&(id.clone(), SignerOrdering(usize::MAX)).into()),
+            ))
+            .filter(|(k, _)| k.id == id)
+            .map(|(_, v)| v)
+            .next()
+    }
+}
+
+/// Options for a software signer
+///
+/// Adjust the behavior of our software signers and the way a transaction is finalized
+#[derive(Debug, Clone)]
+pub struct SignOptions {
+    /// Whether the signer should trust the `witness_utxo`, if the `non_witness_utxo` hasn't been
+    /// provided
+    ///
+    /// Defaults to `false` to mitigate the "SegWit bug" which should trick the wallet into
+    /// paying a fee larger than expected.
+    ///
+    /// Some wallets, especially if relatively old, might not provide the `non_witness_utxo` for
+    /// SegWit transactions in the PSBT they generate: in those cases setting this to `true`
+    /// should correctly produce a signature, at the expense of an increased trust in the creator
+    /// of the PSBT.
+    ///
+    /// For more details see: <https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd>
+    pub trust_witness_utxo: bool,
+
+    /// Whether the wallet should assume a specific height has been reached when trying to finalize
+    /// a transaction
+    ///
+    /// The wallet will only "use" a timelock to satisfy the spending policy of an input if the
+    /// timelock height has already been reached. This option allows overriding the "current height" to let the
+    /// wallet use timelocks in the future to spend a coin.
+    pub assume_height: Option<u32>,
+
+    /// Whether the signer should use the `sighash_type` set in the PSBT when signing, no matter
+    /// what its value is
+    ///
+    /// Defaults to `false` which will only allow signing using `SIGHASH_ALL`.
+    pub allow_all_sighashes: bool,
+
+    /// Whether to remove partial signatures from the PSBT inputs while finalizing PSBT.
+    ///
+    /// Defaults to `true` which will remove partial signatures during finalization.
+    pub remove_partial_sigs: bool,
+
+    /// Whether to remove taproot specific fields from the PSBT on finalization.
+    ///
+    /// For inputs this includes the taproot internal key, merkle root, and individual
+    /// scripts and signatures. For both inputs and outputs it includes key origin info.
+    ///
+    /// Defaults to `true` which will remove all of the above mentioned fields when finalizing.
+    ///
+    /// See [`BIP371`](https://github.com/bitcoin/bips/blob/master/bip-0371.mediawiki) for details.
+    pub remove_taproot_extras: bool,
+
+    /// Whether to try finalizing the PSBT after the inputs are signed.
+    ///
+    /// Defaults to `true` which will try finalizing PSBT after inputs are signed.
+    pub try_finalize: bool,
+
+    /// Specifies which Taproot script-spend leaves we should sign for. This option is
+    /// ignored if we're signing a non-taproot PSBT.
+    ///
+    /// Defaults to All, i.e., the wallet will sign all the leaves it has a key for.
+    pub tap_leaves_options: TapLeavesOptions,
+
+    /// Whether we should try to sign a taproot transaction with the taproot internal key
+    /// or not. This option is ignored if we're signing a non-taproot PSBT.
+    ///
+    /// Defaults to `true`, i.e., we always try to sign with the taproot internal key.
+    pub sign_with_tap_internal_key: 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.
+    pub allow_grinding: bool,
+}
+
+/// Customize which taproot script-path leaves the signer should sign.
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
+pub enum TapLeavesOptions {
+    /// The signer will sign all the leaves it has a key for.
+    #[default]
+    All,
+    /// The signer won't sign leaves other than the ones specified. Note that it could still ignore
+    /// some of the specified leaves, if it doesn't have the right key to sign them.
+    Include(Vec<taproot::TapLeafHash>),
+    /// The signer won't sign the specified leaves.
+    Exclude(Vec<taproot::TapLeafHash>),
+    /// The signer won't sign any leaf.
+    None,
+}
+
+impl Default for SignOptions {
+    fn default() -> Self {
+        SignOptions {
+            trust_witness_utxo: false,
+            assume_height: None,
+            allow_all_sighashes: false,
+            remove_partial_sigs: true,
+            remove_taproot_extras: true,
+            try_finalize: true,
+            tap_leaves_options: TapLeavesOptions::default(),
+            sign_with_tap_internal_key: true,
+            allow_grinding: true,
+        }
+    }
+}
+
+pub(crate) trait ComputeSighash {
+    type Extra;
+    type Sighash;
+    type SighashType;
+
+    fn sighash(
+        psbt: &Psbt,
+        input_index: usize,
+        extra: Self::Extra,
+    ) -> Result<(Self::Sighash, Self::SighashType), SignerError>;
+}
+
+impl ComputeSighash for Legacy {
+    type Extra = ();
+    type Sighash = sighash::LegacySighash;
+    type SighashType = EcdsaSighashType;
+
+    fn sighash(
+        psbt: &Psbt,
+        input_index: usize,
+        _extra: (),
+    ) -> Result<(Self::Sighash, Self::SighashType), SignerError> {
+        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+        let tx_input = &psbt.unsigned_tx.input[input_index];
+
+        let sighash = psbt_input
+            .sighash_type
+            .unwrap_or_else(|| EcdsaSighashType::All.into())
+            .ecdsa_hash_ty()
+            .map_err(|_| SignerError::InvalidSighash)?;
+        let script = match psbt_input.redeem_script {
+            Some(ref redeem_script) => redeem_script.clone(),
+            None => {
+                let non_witness_utxo = psbt_input
+                    .non_witness_utxo
+                    .as_ref()
+                    .ok_or(SignerError::MissingNonWitnessUtxo)?;
+                let prev_out = non_witness_utxo
+                    .output
+                    .get(tx_input.previous_output.vout as usize)
+                    .ok_or(SignerError::InvalidNonWitnessUtxo)?;
+
+                prev_out.script_pubkey.clone()
+            }
+        };
+
+        Ok((
+            sighash::SighashCache::new(&psbt.unsigned_tx).legacy_signature_hash(
+                input_index,
+                &script,
+                sighash.to_u32(),
+            )?,
+            sighash,
+        ))
+    }
+}
+
+impl ComputeSighash for Segwitv0 {
+    type Extra = ();
+    type Sighash = sighash::SegwitV0Sighash;
+    type SighashType = EcdsaSighashType;
+
+    fn sighash(
+        psbt: &Psbt,
+        input_index: usize,
+        _extra: (),
+    ) -> Result<(Self::Sighash, Self::SighashType), SignerError> {
+        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+        let tx_input = &psbt.unsigned_tx.input[input_index];
+
+        let sighash_type = psbt_input
+            .sighash_type
+            .unwrap_or_else(|| EcdsaSighashType::All.into())
+            .ecdsa_hash_ty()
+            .map_err(|_| SignerError::InvalidSighash)?;
+
+        // Always try first with the non-witness utxo
+        let utxo = if let Some(prev_tx) = &psbt_input.non_witness_utxo {
+            // Check the provided prev-tx
+            if prev_tx.txid() != tx_input.previous_output.txid {
+                return Err(SignerError::InvalidNonWitnessUtxo);
+            }
+
+            // The output should be present, if it's missing the `non_witness_utxo` is invalid
+            prev_tx
+                .output
+                .get(tx_input.previous_output.vout as usize)
+                .ok_or(SignerError::InvalidNonWitnessUtxo)?
+        } else if let Some(witness_utxo) = &psbt_input.witness_utxo {
+            // Fallback to the witness_utxo. If we aren't allowed to use it, signing should fail
+            // before we get to this point
+            witness_utxo
+        } else {
+            // Nothing has been provided
+            return Err(SignerError::MissingNonWitnessUtxo);
+        };
+        let value = utxo.value;
+
+        let mut sighasher = sighash::SighashCache::new(&psbt.unsigned_tx);
+
+        let sighash = match psbt_input.witness_script {
+            Some(ref witness_script) => {
+                sighasher.p2wsh_signature_hash(input_index, witness_script, value, sighash_type)?
+            }
+            None => {
+                if utxo.script_pubkey.is_p2wpkh() {
+                    sighasher.p2wpkh_signature_hash(
+                        input_index,
+                        &utxo.script_pubkey,
+                        value,
+                        sighash_type,
+                    )?
+                } else if psbt_input
+                    .redeem_script
+                    .as_ref()
+                    .map(|s| s.is_p2wpkh())
+                    .unwrap_or(false)
+                {
+                    let script_pubkey = psbt_input.redeem_script.as_ref().unwrap();
+                    sighasher.p2wpkh_signature_hash(
+                        input_index,
+                        script_pubkey,
+                        value,
+                        sighash_type,
+                    )?
+                } else {
+                    return Err(SignerError::MissingWitnessScript);
+                }
+            }
+        };
+        Ok((sighash, sighash_type))
+    }
+}
+
+impl ComputeSighash for Tap {
+    type Extra = Option<taproot::TapLeafHash>;
+    type Sighash = TapSighash;
+    type SighashType = TapSighashType;
+
+    fn sighash(
+        psbt: &Psbt,
+        input_index: usize,
+        extra: Self::Extra,
+    ) -> Result<(Self::Sighash, TapSighashType), SignerError> {
+        if input_index >= psbt.inputs.len() || input_index >= psbt.unsigned_tx.input.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+
+        let sighash_type = psbt_input
+            .sighash_type
+            .unwrap_or_else(|| TapSighashType::Default.into())
+            .taproot_hash_ty()
+            .map_err(|_| SignerError::InvalidSighash)?;
+        let witness_utxos = (0..psbt.inputs.len())
+            .map(|i| psbt.get_utxo_for(i))
+            .collect::<Vec<_>>();
+        let mut all_witness_utxos = vec![];
+
+        let mut cache = sighash::SighashCache::new(&psbt.unsigned_tx);
+        let is_anyone_can_pay = psbt::PsbtSighashType::from(sighash_type).to_u32() & 0x80 != 0;
+        let prevouts = if is_anyone_can_pay {
+            sighash::Prevouts::One(
+                input_index,
+                witness_utxos[input_index]
+                    .as_ref()
+                    .ok_or(SignerError::MissingWitnessUtxo)?,
+            )
+        } else if witness_utxos.iter().all(Option::is_some) {
+            all_witness_utxos.extend(witness_utxos.iter().filter_map(|x| x.as_ref()));
+            sighash::Prevouts::All(&all_witness_utxos)
+        } else {
+            return Err(SignerError::MissingWitnessUtxo);
+        };
+
+        // Assume no OP_CODESEPARATOR
+        let extra = extra.map(|leaf_hash| (leaf_hash, 0xFFFFFFFF));
+
+        Ok((
+            cache.taproot_signature_hash(input_index, &prevouts, None, extra, sighash_type)?,
+            sighash_type,
+        ))
+    }
+}
+
+impl PartialOrd for SignersContainerKey {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for SignersContainerKey {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.ordering
+            .cmp(&other.ordering)
+            .then(self.id.cmp(&other.id))
+    }
+}
+
+impl PartialEq for SignersContainerKey {
+    fn eq(&self, other: &Self) -> bool {
+        self.id == other.id && self.ordering == other.ordering
+    }
+}
+
+impl Eq for SignersContainerKey {}
+
+#[cfg(test)]
+mod signers_container_tests {
+    use super::*;
+    use crate::descriptor;
+    use crate::descriptor::IntoWalletDescriptor;
+    use crate::keys::{DescriptorKey, IntoDescriptorKey};
+    use assert_matches::assert_matches;
+    use bitcoin::bip32;
+    use bitcoin::secp256k1::{All, Secp256k1};
+    use bitcoin::Network;
+    use core::str::FromStr;
+    use miniscript::ScriptContext;
+
+    fn is_equal(this: &Arc<dyn TransactionSigner>, that: &Arc<DummySigner>) -> bool {
+        let secp = Secp256k1::new();
+        this.id(&secp) == that.id(&secp)
+    }
+
+    // Signers added with the same ordering (like `Ordering::default`) created from `KeyMap`
+    // should be preserved and not overwritten.
+    // This happens usually when a set of signers is created from a descriptor with private keys.
+    #[test]
+    fn signers_with_same_ordering() {
+        let secp = Secp256k1::new();
+
+        let (prvkey1, _, _) = setup_keys(TPRV0_STR);
+        let (prvkey2, _, _) = setup_keys(TPRV1_STR);
+        let desc = descriptor!(sh(multi(2, prvkey1, prvkey2))).unwrap();
+        let (wallet_desc, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+
+        let signers = SignersContainer::build(keymap, &wallet_desc, &secp);
+        assert_eq!(signers.ids().len(), 2);
+
+        let signers = signers.signers();
+        assert_eq!(signers.len(), 2);
+    }
+
+    #[test]
+    fn signers_sorted_by_ordering() {
+        let mut signers = SignersContainer::new();
+        let signer1 = Arc::new(DummySigner { number: 1 });
+        let signer2 = Arc::new(DummySigner { number: 2 });
+        let signer3 = Arc::new(DummySigner { number: 3 });
+
+        // Mixed order insertions verifies we are not inserting at head or tail.
+        signers.add_external(SignerId::Dummy(2), SignerOrdering(2), signer2.clone());
+        signers.add_external(SignerId::Dummy(1), SignerOrdering(1), signer1.clone());
+        signers.add_external(SignerId::Dummy(3), SignerOrdering(3), signer3.clone());
+
+        // Check that signers are sorted from lowest to highest ordering
+        let signers = signers.signers();
+
+        assert!(is_equal(signers[0], &signer1));
+        assert!(is_equal(signers[1], &signer2));
+        assert!(is_equal(signers[2], &signer3));
+    }
+
+    #[test]
+    fn find_signer_by_id() {
+        let mut signers = SignersContainer::new();
+        let signer1 = Arc::new(DummySigner { number: 1 });
+        let signer2 = Arc::new(DummySigner { number: 2 });
+        let signer3 = Arc::new(DummySigner { number: 3 });
+        let signer4 = Arc::new(DummySigner { number: 3 }); // Same ID as `signer3` but will use lower ordering.
+
+        let id1 = SignerId::Dummy(1);
+        let id2 = SignerId::Dummy(2);
+        let id3 = SignerId::Dummy(3);
+        let id_nonexistent = SignerId::Dummy(999);
+
+        signers.add_external(id1.clone(), SignerOrdering(1), signer1.clone());
+        signers.add_external(id2.clone(), SignerOrdering(2), signer2.clone());
+        signers.add_external(id3.clone(), SignerOrdering(3), signer3.clone());
+
+        assert_matches!(signers.find(id1), Some(signer) if is_equal(signer, &signer1));
+        assert_matches!(signers.find(id2), Some(signer) if is_equal(signer, &signer2));
+        assert_matches!(signers.find(id3.clone()), Some(signer) if is_equal(signer, &signer3));
+
+        // The `signer4` has the same ID as `signer3` but lower ordering.
+        // It should be found by `id3` instead of `signer3`.
+        signers.add_external(id3.clone(), SignerOrdering(2), signer4.clone());
+        assert_matches!(signers.find(id3), Some(signer) if is_equal(signer, &signer4));
+
+        // Can't find anything with ID that doesn't exist
+        assert_matches!(signers.find(id_nonexistent), None);
+    }
+
+    #[derive(Debug, Clone, Copy)]
+    struct DummySigner {
+        number: u64,
+    }
+
+    impl SignerCommon for DummySigner {
+        fn id(&self, _secp: &SecpCtx) -> SignerId {
+            SignerId::Dummy(self.number)
+        }
+    }
+
+    impl TransactionSigner for DummySigner {
+        fn sign_transaction(
+            &self,
+            _psbt: &mut Psbt,
+            _sign_options: &SignOptions,
+            _secp: &SecpCtx,
+        ) -> Result<(), SignerError> {
+            Ok(())
+        }
+    }
+
+    const TPRV0_STR:&str = "tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf";
+    const TPRV1_STR:&str = "tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N";
+
+    const PATH: &str = "m/44'/1'/0'/0";
+
+    fn setup_keys<Ctx: ScriptContext>(
+        tprv: &str,
+    ) -> (DescriptorKey<Ctx>, DescriptorKey<Ctx>, Fingerprint) {
+        let secp: Secp256k1<All> = Secp256k1::new();
+        let path = bip32::DerivationPath::from_str(PATH).unwrap();
+        let tprv = bip32::Xpriv::from_str(tprv).unwrap();
+        let tpub = bip32::Xpub::from_priv(&secp, &tprv);
+        let fingerprint = tprv.fingerprint(&secp);
+        let prvkey = (tprv, path.clone()).into_descriptor_key().unwrap();
+        let pubkey = (tpub, path).into_descriptor_key().unwrap();
+
+        (prvkey, pubkey, fingerprint)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/tx_builder.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/tx_builder.rs.html new file mode 100644 index 0000000000..58477ab5ed --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/tx_builder.rs.html @@ -0,0 +1,2169 @@ +tx_builder.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
+
// 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.
+
+//! Transaction builder
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bdk_wallet::*;
+//! # use bdk_wallet::wallet::ChangeSet;
+//! # use bdk_wallet::wallet::error::CreateTxError;
+//! # use bdk_wallet::wallet::tx_builder::CreateTx;
+//! # use bdk_persist::PersistBackend;
+//! # use anyhow::Error;
+//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
+//! # let mut wallet = doctest_wallet!();
+//! // create a TxBuilder from a wallet
+//! let mut tx_builder = wallet.build_tx();
+//!
+//! tx_builder
+//!     // Create a transaction with one output to `to_address` of 50_000 satoshi
+//!     .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
+//!     // With a custom fee rate of 5.0 satoshi/vbyte
+//!     .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
+//!     // Only spend non-change outputs
+//!     .do_not_spend_change()
+//!     // Turn on RBF signaling
+//!     .enable_rbf();
+//! let psbt = tx_builder.finish()?;
+//! # Ok::<(), anyhow::Error>(())
+//! ```
+
+use alloc::{boxed::Box, rc::Rc, string::String, vec::Vec};
+use core::cell::RefCell;
+use core::fmt;
+use core::marker::PhantomData;
+
+use bitcoin::psbt::{self, Psbt};
+use bitcoin::script::PushBytes;
+use bitcoin::{absolute, Amount, FeeRate, OutPoint, ScriptBuf, Sequence, Transaction, Txid};
+
+use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
+use super::{CreateTxError, Wallet};
+use crate::collections::{BTreeMap, HashSet};
+use crate::{KeychainKind, LocalOutput, Utxo, WeightedUtxo};
+
+/// Context in which the [`TxBuilder`] is valid
+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).
+#[derive(Debug, Default, Clone)]
+pub struct CreateTx;
+impl TxBuilderContext for CreateTx {}
+
+/// Marker type to indicate the [`TxBuilder`] is being used to bump the fee of an existing transaction.
+#[derive(Debug, Default, Clone)]
+pub struct BumpFee;
+impl TxBuilderContext for BumpFee {}
+
+/// 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.
+///
+/// Each option setting method on `TxBuilder` takes and returns `&mut self` so you can chain calls
+/// as in the following example:
+///
+/// ```
+/// # use bdk_wallet::*;
+/// # use bdk_wallet::wallet::tx_builder::*;
+/// # use bitcoin::*;
+/// # use core::str::FromStr;
+/// # use bdk_wallet::wallet::ChangeSet;
+/// # use bdk_wallet::wallet::error::CreateTxError;
+/// # use bdk_persist::PersistBackend;
+/// # use anyhow::Error;
+/// # let mut wallet = doctest_wallet!();
+/// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap().assume_checked();
+/// # let addr2 = addr1.clone();
+/// // chaining
+/// let psbt1 = {
+///     let mut builder = wallet.build_tx();
+///     builder
+///         .ordering(TxOrdering::Untouched)
+///         .add_recipient(addr1.script_pubkey(), Amount::from_sat(50_000))
+///         .add_recipient(addr2.script_pubkey(), Amount::from_sat(50_000));
+///     builder.finish()?
+/// };
+///
+/// // non-chaining
+/// let psbt2 = {
+///     let mut builder = wallet.build_tx();
+///     builder.ordering(TxOrdering::Untouched);
+///     for addr in &[addr1, addr2] {
+///         builder.add_recipient(addr.script_pubkey(), Amount::from_sat(50_000));
+///     }
+///     builder.finish()?
+/// };
+///
+/// assert_eq!(psbt1.unsigned_tx.output[..2], psbt2.unsigned_tx.output[..2]);
+/// # Ok::<(), anyhow::Error>(())
+/// ```
+///
+/// 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](super::tx_builder)'s documentation;
+///
+/// [`build_tx`]: Wallet::build_tx
+/// [`build_fee_bump`]: Wallet::build_fee_bump
+/// [`finish`]: Self::finish
+/// [`coin_selection`]: Self::coin_selection
+#[derive(Debug)]
+pub struct TxBuilder<'a, Cs, Ctx> {
+    pub(crate) wallet: Rc<RefCell<&'a mut Wallet>>,
+    pub(crate) params: TxParams,
+    pub(crate) coin_selection: Cs,
+    pub(crate) phantom: PhantomData<Ctx>,
+}
+
+/// The parameters for transaction creation sans coin selection algorithm.
+//TODO: TxParams should eventually be exposed publicly.
+#[derive(Default, Debug, Clone)]
+pub(crate) struct TxParams {
+    pub(crate) recipients: Vec<(ScriptBuf, u64)>,
+    pub(crate) drain_wallet: bool,
+    pub(crate) drain_to: Option<ScriptBuf>,
+    pub(crate) fee_policy: Option<FeePolicy>,
+    pub(crate) internal_policy_path: Option<BTreeMap<String, Vec<usize>>>,
+    pub(crate) external_policy_path: Option<BTreeMap<String, Vec<usize>>>,
+    pub(crate) utxos: Vec<WeightedUtxo>,
+    pub(crate) unspendable: HashSet<OutPoint>,
+    pub(crate) manually_selected_only: bool,
+    pub(crate) sighash: Option<psbt::PsbtSighashType>,
+    pub(crate) ordering: TxOrdering,
+    pub(crate) locktime: Option<absolute::LockTime>,
+    pub(crate) rbf: Option<RbfValue>,
+    pub(crate) version: Option<Version>,
+    pub(crate) change_policy: ChangeSpendPolicy,
+    pub(crate) only_witness_utxo: bool,
+    pub(crate) add_global_xpubs: bool,
+    pub(crate) include_output_redeem_witness_script: bool,
+    pub(crate) bumping_fee: Option<PreviousFee>,
+    pub(crate) current_height: Option<absolute::LockTime>,
+    pub(crate) allow_dust: bool,
+}
+
+#[derive(Clone, Copy, Debug)]
+pub(crate) struct PreviousFee {
+    pub absolute: u64,
+    pub rate: FeeRate,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub(crate) enum FeePolicy {
+    FeeRate(FeeRate),
+    FeeAmount(u64),
+}
+
+impl Default for FeePolicy {
+    fn default() -> Self {
+        FeePolicy::FeeRate(FeeRate::BROADCAST_MIN)
+    }
+}
+
+impl<'a, Cs: Clone, Ctx> Clone for TxBuilder<'a, Cs, Ctx> {
+    fn clone(&self) -> Self {
+        TxBuilder {
+            wallet: self.wallet.clone(),
+            params: self.params.clone(),
+            coin_selection: self.coin_selection.clone(),
+            phantom: PhantomData,
+        }
+    }
+}
+
+// methods supported by both contexts, for any CoinSelectionAlgorithm
+impl<'a, Cs, Ctx> TxBuilder<'a, Cs, Ctx> {
+    /// Set a custom fee rate.
+    ///
+    /// This method sets the mining fee paid by the transaction as a rate on its size.
+    /// This means that the total fee paid is equal to `fee_rate` times the size
+    /// of the transaction. Default is 1 sat/vB in accordance with Bitcoin Core's default
+    /// relay policy.
+    ///
+    /// Note that this is really a minimum feerate -- it's possible to
+    /// overshoot it slightly since adding a change output to drain the remaining
+    /// excess might not be viable.
+    pub fn fee_rate(&mut self, fee_rate: FeeRate) -> &mut Self {
+        self.params.fee_policy = Some(FeePolicy::FeeRate(fee_rate));
+        self
+    }
+
+    /// Set an absolute fee
+    /// The fee_absolute method refers to the absolute transaction fee in satoshis (sats).
+    /// If anyone sets both the fee_absolute method and the fee_rate method,
+    /// the FeePolicy enum will be set by whichever method was called last,
+    /// as the FeeRate and FeeAmount are mutually exclusive.
+    ///
+    /// Note that this is really a minimum absolute fee -- it's possible to
+    /// overshoot it slightly since adding a change output to drain the remaining
+    /// excess might not be viable.
+    pub fn fee_absolute(&mut self, fee_amount: u64) -> &mut Self {
+        self.params.fee_policy = Some(FeePolicy::FeeAmount(fee_amount));
+        self
+    }
+
+    /// 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`](crate::descriptor::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
+    /// [`SatisfiableItem::Thresh::items`](crate::descriptor::policy::SatisfiableItem::Thresh::items)).
+    ///
+    /// ## Example
+    ///
+    /// An example of when the policy path is needed is the following descriptor:
+    /// `wsh(thresh(2,pk(A),sj:and_v(v:pk(B),n:older(6)),snj:and_v(v:pk(C),after(630000))))`,
+    /// derived from the miniscript policy `thresh(2,pk(A),and(pk(B),older(6)),and(pk(C),after(630000)))`.
+    /// It declares three descriptor fragments, and at the top level it uses `thresh()` to
+    /// ensure that at least two of them are satisfied. The individual fragments are:
+    ///
+    /// 1. `pk(A)`
+    /// 2. `and(pk(B),older(6))`
+    /// 3. `and(pk(C),after(630000))`
+    ///
+    /// When those conditions are combined in pairs, it's clear that the transaction needs to be created
+    /// differently depending on how the user intends to satisfy the policy afterwards:
+    ///
+    /// * If fragments `1` and `2` are used, the transaction will need to use a specific
+    ///   `n_sequence` in order to spend an `OP_CSV` branch.
+    /// * If fragments `1` and `3` are used, the transaction will need to use a specific `locktime`
+    ///   in order to spend an `OP_CLTV` branch.
+    /// * If fragments `2` and `3` are used, the transaction will need both.
+    ///
+    /// When the spending policy is represented as a tree (see
+    /// [`Wallet::policies`](super::Wallet::policies)), every node
+    /// is assigned a unique identifier that can be used in the policy path to specify which of
+    /// the node's children the user intends to satisfy: for instance, assuming the `thresh()`
+    /// root node of this example has an id of `aabbccdd`, the policy path map would look like:
+    ///
+    /// `{ "aabbccdd" => [0, 1] }`
+    ///
+    /// where the key is the node's id, and the value is a list of the children that should be
+    /// used, in no particular order.
+    ///
+    /// If a particularly complex descriptor has multiple ambiguous thresholds in its structure,
+    /// multiple entries can be added to the map, one for each node that requires an explicit path.
+    ///
+    /// ```
+    /// # use std::str::FromStr;
+    /// # use std::collections::BTreeMap;
+    /// # use bitcoin::*;
+    /// # use bdk_wallet::*;
+    /// # let to_address =
+    /// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
+    ///     .unwrap()
+    ///     .assume_checked();
+    /// # let mut wallet = doctest_wallet!();
+    /// let mut path = BTreeMap::new();
+    /// path.insert("aabbccdd".to_string(), vec![0, 1]);
+    ///
+    /// let builder = wallet
+    ///     .build_tx()
+    ///     .add_recipient(to_address.script_pubkey(), Amount::from_sat(50_000))
+    ///     .policy_path(path, KeychainKind::External);
+    ///
+    /// # Ok::<(), anyhow::Error>(())
+    /// ```
+    pub fn policy_path(
+        &mut self,
+        policy_path: BTreeMap<String, Vec<usize>>,
+        keychain: KeychainKind,
+    ) -> &mut Self {
+        let to_update = match keychain {
+            KeychainKind::Internal => &mut self.params.internal_policy_path,
+            KeychainKind::External => &mut self.params.external_policy_path,
+        };
+
+        *to_update = Some(policy_path);
+        self
+    }
+
+    /// 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.
+    pub fn add_utxos(&mut self, outpoints: &[OutPoint]) -> Result<&mut Self, AddUtxoError> {
+        {
+            let wallet = self.wallet.borrow();
+            let utxos = outpoints
+                .iter()
+                .map(|outpoint| {
+                    wallet
+                        .get_utxo(*outpoint)
+                        .ok_or(AddUtxoError::UnknownUtxo(*outpoint))
+                })
+                .collect::<Result<Vec<_>, _>>()?;
+
+            for utxo in utxos {
+                let descriptor = wallet.get_descriptor_for_keychain(utxo.keychain);
+                let satisfaction_weight = descriptor.max_weight_to_satisfy().unwrap();
+                self.params.utxos.push(WeightedUtxo {
+                    satisfaction_weight,
+                    utxo: Utxo::Local(utxo),
+                });
+            }
+        }
+
+        Ok(self)
+    }
+
+    /// 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.
+    pub fn add_utxo(&mut self, outpoint: OutPoint) -> Result<&mut Self, AddUtxoError> {
+        self.add_utxos(&[outpoint])
+    }
+
+    /// 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. `psbt_input`: To know the value.
+    /// 3. `satisfaction_weight`: To know how much weight/vbytes the input will add to the transaction for fee calculation.
+    ///
+    /// There are several security concerns about adding foreign UTXOs that application
+    /// developers should consider. First, how do you know the value of the input is correct? If a
+    /// `non_witness_utxo` is provided in the `psbt_input` then this method implicitly verifies the
+    /// value by checking it against the transaction. If only a `witness_utxo` is provided then this
+    /// method doesn't verify the value but just takes it as a given -- it is up to you to check
+    /// that whoever sent you the `input_psbt` was not lying!
+    ///
+    /// Secondly, you must somehow provide `satisfaction_weight` of the input. Depending on your
+    /// application it may be important that this be known precisely. If not, a malicious
+    /// counterparty may fool you into putting in a value that is too low, giving the transaction a
+    /// lower than expected feerate. They could also fool you into putting a value that is too high
+    /// causing you to pay a fee that is too high. The party who is broadcasting the transaction can
+    /// of course check the real input weight matches the expected weight prior to broadcasting.
+    ///
+    /// To guarantee the `max_weight_to_satisfy` is correct, you can require the party providing the
+    /// `psbt_input` provide a miniscript descriptor for the input so you can check it against the
+    /// `script_pubkey` and then ask it for the [`max_weight_to_satisfy`].
+    ///
+    /// This is an **EXPERIMENTAL** feature, API and other major changes are expected.
+    ///
+    /// In order to use [`Wallet::calculate_fee`] or [`Wallet::calculate_fee_rate`] for a transaction
+    /// created with foreign UTXO(s) you must manually insert the corresponding TxOut(s) into the tx
+    /// graph using the [`Wallet::insert_txout`] function.
+    ///
+    /// # Errors
+    ///
+    /// This method returns errors in the following circumstances:
+    ///
+    /// 1. The `psbt_input` does not contain a `witness_utxo` or `non_witness_utxo`.
+    /// 2. The data in `non_witness_utxo` does not match what is in `outpoint`.
+    ///
+    /// 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_witness_utxo`]: Self::only_witness_utxo
+    /// [`finish`]: Self::finish
+    /// [`max_weight_to_satisfy`]: miniscript::Descriptor::max_weight_to_satisfy
+    pub fn add_foreign_utxo(
+        &mut self,
+        outpoint: OutPoint,
+        psbt_input: psbt::Input,
+        satisfaction_weight: usize,
+    ) -> Result<&mut Self, AddForeignUtxoError> {
+        self.add_foreign_utxo_with_sequence(
+            outpoint,
+            psbt_input,
+            satisfaction_weight,
+            Sequence::MAX,
+        )
+    }
+
+    /// Same as [add_foreign_utxo](TxBuilder::add_foreign_utxo) but allows to set the nSequence value.
+    pub fn add_foreign_utxo_with_sequence(
+        &mut self,
+        outpoint: OutPoint,
+        psbt_input: psbt::Input,
+        satisfaction_weight: usize,
+        sequence: Sequence,
+    ) -> Result<&mut Self, AddForeignUtxoError> {
+        if psbt_input.witness_utxo.is_none() {
+            match psbt_input.non_witness_utxo.as_ref() {
+                Some(tx) => {
+                    if tx.txid() != outpoint.txid {
+                        return Err(AddForeignUtxoError::InvalidTxid {
+                            input_txid: tx.txid(),
+                            foreign_utxo: outpoint,
+                        });
+                    }
+                    if tx.output.len() <= outpoint.vout as usize {
+                        return Err(AddForeignUtxoError::InvalidOutpoint(outpoint));
+                    }
+                }
+                None => {
+                    return Err(AddForeignUtxoError::MissingUtxo);
+                }
+            }
+        }
+
+        self.params.utxos.push(WeightedUtxo {
+            satisfaction_weight,
+            utxo: Utxo::Foreign {
+                outpoint,
+                sequence: Some(sequence),
+                psbt_input: Box::new(psbt_input),
+            },
+        });
+
+        Ok(self)
+    }
+
+    /// 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.
+    ///
+    /// [`add_utxo`]: Self::add_utxo
+    pub fn manually_selected_only(&mut self) -> &mut Self {
+        self.params.manually_selected_only = true;
+        self
+    }
+
+    /// 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.
+    pub fn unspendable(&mut self, unspendable: Vec<OutPoint>) -> &mut Self {
+        self.params.unspendable = unspendable.into_iter().collect();
+        self
+    }
+
+    /// 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.
+    pub fn add_unspendable(&mut self, unspendable: OutPoint) -> &mut Self {
+        self.params.unspendable.insert(unspendable);
+        self
+    }
+
+    /// Sign with a specific sig hash
+    ///
+    /// **Use this option very carefully**
+    pub fn sighash(&mut self, sighash: psbt::PsbtSighashType) -> &mut Self {
+        self.params.sighash = Some(sighash);
+        self
+    }
+
+    /// Choose the ordering for inputs and outputs of the transaction
+    pub fn ordering(&mut self, ordering: TxOrdering) -> &mut Self {
+        self.params.ordering = ordering;
+        self
+    }
+
+    /// Use a specific nLockTime while creating the transaction
+    ///
+    /// This can cause conflicts if the wallet's descriptors contain an "after" (OP_CLTV) operator.
+    pub fn nlocktime(&mut self, locktime: absolute::LockTime) -> &mut Self {
+        self.params.locktime = Some(locktime);
+        self
+    }
+
+    /// 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.
+    pub fn version(&mut self, version: i32) -> &mut Self {
+        self.params.version = Some(Version(version));
+        self
+    }
+
+    /// Do not spend change outputs
+    ///
+    /// This effectively adds all the change outputs to the "unspendable" list. See
+    /// [`TxBuilder::unspendable`].
+    pub fn do_not_spend_change(&mut self) -> &mut Self {
+        self.params.change_policy = ChangeSpendPolicy::ChangeForbidden;
+        self
+    }
+
+    /// Only spend change outputs
+    ///
+    /// This effectively adds all the non-change outputs to the "unspendable" list. See
+    /// [`TxBuilder::unspendable`].
+    pub fn only_spend_change(&mut self) -> &mut Self {
+        self.params.change_policy = ChangeSpendPolicy::OnlyChange;
+        self
+    }
+
+    /// Set a specific [`ChangeSpendPolicy`]. See [`TxBuilder::do_not_spend_change`] and
+    /// [`TxBuilder::only_spend_change`] for some shortcuts.
+    pub fn change_policy(&mut self, change_policy: ChangeSpendPolicy) -> &mut Self {
+        self.params.change_policy = change_policy;
+        self
+    }
+
+    /// Only Fill-in the [`psbt::Input::witness_utxo`](bitcoin::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`.
+    pub fn only_witness_utxo(&mut self) -> &mut Self {
+        self.params.only_witness_utxo = true;
+        self
+    }
+
+    /// Fill-in the [`psbt::Output::redeem_script`](bitcoin::psbt::Output::redeem_script) and
+    /// [`psbt::Output::witness_script`](bitcoin::psbt::Output::witness_script) fields.
+    ///
+    /// This is useful for signers which always require it, like ColdCard hardware wallets.
+    pub fn include_output_redeem_witness_script(&mut self) -> &mut Self {
+        self.params.include_output_redeem_witness_script = true;
+        self
+    }
+
+    /// 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.
+    pub fn add_global_xpubs(&mut self) -> &mut Self {
+        self.params.add_global_xpubs = true;
+        self
+    }
+
+    /// Spend all the available inputs. This respects filters like [`TxBuilder::unspendable`] and the change policy.
+    pub fn drain_wallet(&mut self) -> &mut Self {
+        self.params.drain_wallet = true;
+        self
+    }
+
+    /// 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.
+    pub fn coin_selection<P: CoinSelectionAlgorithm>(
+        self,
+        coin_selection: P,
+    ) -> TxBuilder<'a, P, Ctx> {
+        TxBuilder {
+            wallet: self.wallet,
+            params: self.params,
+            coin_selection,
+            phantom: PhantomData,
+        }
+    }
+
+    /// Enable signaling RBF
+    ///
+    /// This will use the default nSequence value of `0xFFFFFFFD`.
+    pub fn enable_rbf(&mut self) -> &mut Self {
+        self.params.rbf = Some(RbfValue::Default);
+        self
+    }
+
+    /// 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.
+    pub fn enable_rbf_with_sequence(&mut self, nsequence: Sequence) -> &mut Self {
+        self.params.rbf = Some(RbfValue::Value(nsequence));
+        self
+    }
+
+    /// Set the current blockchain height.
+    ///
+    /// This will be used to:
+    /// 1. Set the nLockTime for preventing fee sniping.
+    /// **Note**: This will be ignored if you manually specify a nlocktime using [`TxBuilder::nlocktime`].
+    /// 2. Decide whether coinbase outputs are mature or not. If the coinbase outputs are not
+    ///    mature at `current_height`, we ignore them in the coin selection.
+    ///    If you want to create a transaction that spends immature coinbase inputs, manually
+    ///    add them using [`TxBuilder::add_utxos`].
+    ///
+    /// In both cases, if you don't provide a current height, we use the last sync height.
+    pub fn current_height(&mut self, height: u32) -> &mut Self {
+        self.params.current_height =
+            Some(absolute::LockTime::from_height(height).expect("Invalid height"));
+        self
+    }
+
+    /// 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.
+    pub fn allow_dust(&mut self, allow_dust: bool) -> &mut Self {
+        self.params.allow_dust = allow_dust;
+        self
+    }
+}
+
+impl<'a, Cs: CoinSelectionAlgorithm, Ctx> TxBuilder<'a, Cs, Ctx> {
+    /// Finish building the transaction.
+    ///
+    /// Returns a new [`Psbt`] per [`BIP174`].
+    ///
+    /// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
+    pub fn finish(self) -> Result<Psbt, CreateTxError> {
+        self.wallet
+            .borrow_mut()
+            .create_tx(self.coin_selection, self.params)
+    }
+}
+
+#[derive(Debug)]
+/// Error returned from [`TxBuilder::add_utxo`] and [`TxBuilder::add_utxos`]
+pub enum AddUtxoError {
+    /// Happens when trying to spend an UTXO that is not in the internal database
+    UnknownUtxo(OutPoint),
+}
+
+impl fmt::Display for AddUtxoError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::UnknownUtxo(outpoint) => write!(
+                f,
+                "UTXO not found in the internal database for txid: {} with vout: {}",
+                outpoint.txid, outpoint.vout
+            ),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for AddUtxoError {}
+
+#[derive(Debug)]
+/// Error returned from [`TxBuilder::add_foreign_utxo`].
+pub enum AddForeignUtxoError {
+    /// Foreign utxo outpoint txid does not match PSBT input txid
+    InvalidTxid {
+        /// PSBT input txid
+        input_txid: Txid,
+        /// Foreign UTXO outpoint
+        foreign_utxo: OutPoint,
+    },
+    /// Requested outpoint doesn't exist in the tx (vout greater than available outputs)
+    InvalidOutpoint(OutPoint),
+    /// Foreign utxo missing witness_utxo or non_witness_utxo
+    MissingUtxo,
+}
+
+impl fmt::Display for AddForeignUtxoError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::InvalidTxid {
+                input_txid,
+                foreign_utxo,
+            } => write!(
+                f,
+                "Foreign UTXO outpoint txid: {} does not match PSBT input txid: {}",
+                foreign_utxo.txid, input_txid,
+            ),
+            Self::InvalidOutpoint(outpoint) => write!(
+                f,
+                "Requested outpoint doesn't exist for txid: {} with vout: {}",
+                outpoint.txid, outpoint.vout,
+            ),
+            Self::MissingUtxo => write!(f, "Foreign utxo missing witness_utxo or non_witness_utxo"),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for AddForeignUtxoError {}
+
+#[derive(Debug)]
+/// Error returned from [`TxBuilder::allow_shrinking`]
+pub enum AllowShrinkingError {
+    /// Script/PubKey was not in the original transaction
+    MissingScriptPubKey(ScriptBuf),
+}
+
+impl fmt::Display for AllowShrinkingError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::MissingScriptPubKey(script_buf) => write!(
+                f,
+                "Script/PubKey was not in the original transaction: {}",
+                script_buf,
+            ),
+        }
+    }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for AllowShrinkingError {}
+
+impl<'a, Cs: CoinSelectionAlgorithm> TxBuilder<'a, Cs, CreateTx> {
+    /// Replace the recipients already added with a new list
+    pub fn set_recipients(&mut self, recipients: Vec<(ScriptBuf, Amount)>) -> &mut Self {
+        self.params.recipients = recipients
+            .into_iter()
+            .map(|(script, amount)| (script, amount.to_sat()))
+            .collect();
+        self
+    }
+
+    /// Add a recipient to the internal list
+    pub fn add_recipient(&mut self, script_pubkey: ScriptBuf, amount: Amount) -> &mut Self {
+        self.params
+            .recipients
+            .push((script_pubkey, amount.to_sat()));
+        self
+    }
+
+    /// Add data as an output, using OP_RETURN
+    pub fn add_data<T: AsRef<PushBytes>>(&mut self, data: &T) -> &mut Self {
+        let script = ScriptBuf::new_op_return(data);
+        self.add_recipient(script, Amount::ZERO);
+        self
+    }
+
+    /// 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
+    /// coins are too small) it will not be included in the resulting transaction. The only
+    /// difference is that it is valid to use `drain_to` without setting any ordinary recipients
+    /// with [`add_recipient`] (but it is perfectly fine to add recipients as well).
+    ///
+    /// If you choose not to set any recipients, you should either provide the utxos that the
+    /// transaction should spend via [`add_utxos`], or set [`drain_wallet`] to spend all of them.
+    ///
+    /// When bumping the fees of a transaction made with this option, you probably want to
+    /// use [`allow_shrinking`] to allow this output to be reduced to pay for the extra fees.
+    ///
+    /// # Example
+    ///
+    /// `drain_to` is very useful for draining all the coins in a wallet with [`drain_wallet`] to a
+    /// single address.
+    ///
+    /// ```
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk_wallet::*;
+    /// # use bdk_wallet::wallet::ChangeSet;
+    /// # use bdk_wallet::wallet::error::CreateTxError;
+    /// # use bdk_wallet::wallet::tx_builder::CreateTx;
+    /// # use bdk_persist::PersistBackend;
+    /// # use anyhow::Error;
+    /// # let to_address =
+    /// Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt")
+    ///     .unwrap()
+    ///     .assume_checked();
+    /// # let mut wallet = doctest_wallet!();
+    /// let mut tx_builder = wallet.build_tx();
+    ///
+    /// tx_builder
+    ///     // Spend all outputs in this wallet.
+    ///     .drain_wallet()
+    ///     // Send the excess (which is all the coins minus the fee) to this address.
+    ///     .drain_to(to_address.script_pubkey())
+    ///     .fee_rate(FeeRate::from_sat_per_vb(5).expect("valid feerate"))
+    ///     .enable_rbf();
+    /// let psbt = tx_builder.finish()?;
+    /// # Ok::<(), anyhow::Error>(())
+    /// ```
+    ///
+    /// [`allow_shrinking`]: Self::allow_shrinking
+    /// [`add_recipient`]: Self::add_recipient
+    /// [`add_utxos`]: Self::add_utxos
+    /// [`drain_wallet`]: Self::drain_wallet
+    pub fn drain_to(&mut self, script_pubkey: ScriptBuf) -> &mut Self {
+        self.params.drain_to = Some(script_pubkey);
+        self
+    }
+}
+
+// methods supported only by bump_fee
+impl<'a> TxBuilder<'a, 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.
+    ///
+    /// **Note** that the output may shrink to below the dust limit and therefore be removed. If it is
+    /// preserved then it is currently not guaranteed to be in the same position as it was
+    /// originally.
+    ///
+    /// Returns an `Err` if `script_pubkey` can't be found among the recipients of the
+    /// transaction we are bumping.
+    pub fn allow_shrinking(
+        &mut self,
+        script_pubkey: ScriptBuf,
+    ) -> Result<&mut Self, AllowShrinkingError> {
+        match self
+            .params
+            .recipients
+            .iter()
+            .position(|(recipient_script, _)| *recipient_script == script_pubkey)
+        {
+            Some(position) => {
+                self.params.recipients.remove(position);
+                self.params.drain_to = Some(script_pubkey);
+                Ok(self)
+            }
+            None => Err(AllowShrinkingError::MissingScriptPubKey(script_pubkey)),
+        }
+    }
+}
+
+/// Ordering of the transaction's inputs and outputs
+#[derive(Default, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum TxOrdering {
+    /// Randomized (default)
+    #[default]
+    Shuffle,
+    /// Unchanged
+    Untouched,
+    /// BIP69 / Lexicographic
+    Bip69Lexicographic,
+}
+
+impl TxOrdering {
+    /// Sort transaction inputs and outputs by [`TxOrdering`] variant
+    pub fn sort_tx(&self, tx: &mut Transaction) {
+        match self {
+            TxOrdering::Untouched => {}
+            TxOrdering::Shuffle => {
+                use rand::seq::SliceRandom;
+                let mut rng = rand::thread_rng();
+                tx.input.shuffle(&mut rng);
+                tx.output.shuffle(&mut rng);
+            }
+            TxOrdering::Bip69Lexicographic => {
+                tx.input.sort_unstable_by_key(|txin| {
+                    (txin.previous_output.txid, txin.previous_output.vout)
+                });
+                tx.output
+                    .sort_unstable_by_key(|txout| (txout.value, txout.script_pubkey.clone()));
+            }
+        }
+    }
+}
+
+/// Transaction version
+///
+/// Has a default value of `1`
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub(crate) struct Version(pub(crate) i32);
+
+impl Default for Version {
+    fn default() -> Self {
+        Version(1)
+    }
+}
+
+/// RBF nSequence value
+///
+/// Has a default value of `0xFFFFFFFD`
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub(crate) enum RbfValue {
+    Default,
+    Value(Sequence),
+}
+
+impl RbfValue {
+    pub(crate) fn get_value(&self) -> Sequence {
+        match self {
+            RbfValue::Default => Sequence::ENABLE_RBF_NO_LOCKTIME,
+            RbfValue::Value(v) => *v,
+        }
+    }
+}
+
+/// Policy regarding the use of change outputs when creating a transaction
+#[derive(Default, Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum ChangeSpendPolicy {
+    /// Use both change and non-change outputs (default)
+    #[default]
+    ChangeAllowed,
+    /// Only use change outputs (see [`TxBuilder::only_spend_change`])
+    OnlyChange,
+    /// Only use non-change outputs (see [`TxBuilder::do_not_spend_change`])
+    ChangeForbidden,
+}
+
+impl ChangeSpendPolicy {
+    pub(crate) fn is_satisfied_by(&self, utxo: &LocalOutput) -> bool {
+        match self {
+            ChangeSpendPolicy::ChangeAllowed => true,
+            ChangeSpendPolicy::OnlyChange => utxo.keychain == KeychainKind::Internal,
+            ChangeSpendPolicy::ChangeForbidden => utxo.keychain == KeychainKind::External,
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    const ORDERING_TEST_TX: &str = "0200000003c26f3eb7932f7acddc5ddd26602b77e7516079b03090a16e2c2f54\
+                                    85d1fd600f0100000000ffffffffc26f3eb7932f7acddc5ddd26602b77e75160\
+                                    79b03090a16e2c2f5485d1fd600f0000000000ffffffff571fb3e02278217852\
+                                    dd5d299947e2b7354a639adc32ec1fa7b82cfb5dec530e0500000000ffffffff\
+                                    03e80300000000000002aaeee80300000000000001aa200300000000000001ff\
+                                    00000000";
+    macro_rules! ordering_test_tx {
+        () => {
+            deserialize::<bitcoin::Transaction>(&Vec::<u8>::from_hex(ORDERING_TEST_TX).unwrap())
+                .unwrap()
+        };
+    }
+
+    use bdk_chain::ConfirmationTime;
+    use bitcoin::consensus::deserialize;
+    use bitcoin::hex::FromHex;
+    use bitcoin::TxOut;
+
+    use super::*;
+
+    #[test]
+    fn test_output_ordering_default_shuffle() {
+        assert_eq!(TxOrdering::default(), TxOrdering::Shuffle);
+    }
+
+    #[test]
+    fn test_output_ordering_untouched() {
+        let original_tx = ordering_test_tx!();
+        let mut tx = original_tx.clone();
+
+        TxOrdering::Untouched.sort_tx(&mut tx);
+
+        assert_eq!(original_tx, tx);
+    }
+
+    #[test]
+    fn test_output_ordering_shuffle() {
+        let original_tx = ordering_test_tx!();
+        let mut tx = original_tx.clone();
+
+        (0..40)
+            .find(|_| {
+                TxOrdering::Shuffle.sort_tx(&mut tx);
+                original_tx.input != tx.input
+            })
+            .expect("it should have moved the inputs at least once");
+
+        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 core::str::FromStr;
+
+        let original_tx = ordering_test_tx!();
+        let mut tx = original_tx;
+
+        TxOrdering::Bip69Lexicographic.sort_tx(&mut tx);
+
+        assert_eq!(
+            tx.input[0].previous_output,
+            bitcoin::OutPoint::from_str(
+                "0e53ec5dfb2cb8a71fec32dc9a634a35b7e24799295ddd5278217822e0b31f57:5"
+            )
+            .unwrap()
+        );
+        assert_eq!(
+            tx.input[1].previous_output,
+            bitcoin::OutPoint::from_str(
+                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:0"
+            )
+            .unwrap()
+        );
+        assert_eq!(
+            tx.input[2].previous_output,
+            bitcoin::OutPoint::from_str(
+                "0f60fdd185542f2c6ea19030b0796051e7772b6026dd5ddccd7a2f93b73e6fc2:1"
+            )
+            .unwrap()
+        );
+
+        assert_eq!(tx.output[0].value.to_sat(), 800);
+        assert_eq!(tx.output[1].script_pubkey, ScriptBuf::from(vec![0xAA]));
+        assert_eq!(
+            tx.output[2].script_pubkey,
+            ScriptBuf::from(vec![0xAA, 0xEE])
+        );
+    }
+
+    fn get_test_utxos() -> Vec<LocalOutput> {
+        use bitcoin::hashes::Hash;
+
+        vec![
+            LocalOutput {
+                outpoint: OutPoint {
+                    txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(),
+                    vout: 0,
+                },
+                txout: TxOut::NULL,
+                keychain: KeychainKind::External,
+                is_spent: false,
+                confirmation_time: ConfirmationTime::Unconfirmed { last_seen: 0 },
+                derivation_index: 0,
+            },
+            LocalOutput {
+                outpoint: OutPoint {
+                    txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(),
+                    vout: 1,
+                },
+                txout: TxOut::NULL,
+                keychain: KeychainKind::Internal,
+                is_spent: false,
+                confirmation_time: ConfirmationTime::Confirmed {
+                    height: 32,
+                    time: 42,
+                },
+                derivation_index: 1,
+            },
+        ]
+    }
+
+    #[test]
+    fn test_change_spend_policy_default() {
+        let change_spend_policy = ChangeSpendPolicy::default();
+        let filtered = get_test_utxos()
+            .into_iter()
+            .filter(|u| change_spend_policy.is_satisfied_by(u))
+            .count();
+
+        assert_eq!(filtered, 2);
+    }
+
+    #[test]
+    fn test_change_spend_policy_no_internal() {
+        let change_spend_policy = ChangeSpendPolicy::ChangeForbidden;
+        let filtered = get_test_utxos()
+            .into_iter()
+            .filter(|u| change_spend_policy.is_satisfied_by(u))
+            .collect::<Vec<_>>();
+
+        assert_eq!(filtered.len(), 1);
+        assert_eq!(filtered[0].keychain, KeychainKind::External);
+    }
+
+    #[test]
+    fn test_change_spend_policy_only_internal() {
+        let change_spend_policy = ChangeSpendPolicy::OnlyChange;
+        let filtered = get_test_utxos()
+            .into_iter()
+            .filter(|u| change_spend_policy.is_satisfied_by(u))
+            .collect::<Vec<_>>();
+
+        assert_eq!(filtered.len(), 1);
+        assert_eq!(filtered[0].keychain, KeychainKind::Internal);
+    }
+
+    #[test]
+    fn test_default_tx_version_1() {
+        let version = Version::default();
+        assert_eq!(version.0, 1);
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/utils.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/utils.rs.html new file mode 100644 index 0000000000..ec633a826a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk_wallet/wallet/utils.rs.html @@ -0,0 +1,373 @@ +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
+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
+
// 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 bitcoin::secp256k1::{All, Secp256k1};
+use bitcoin::{absolute, Script, Sequence};
+
+use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
+
+/// 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
+// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
+// instead of a <= etc.
+pub trait IsDust {
+    /// Check whether or not a value is below dust limit
+    fn is_dust(&self, script: &Script) -> bool;
+}
+
+impl IsDust for u64 {
+    fn is_dust(&self, script: &Script) -> bool {
+        *self < script.dust_value().to_sat()
+    }
+}
+
+pub struct After {
+    pub current_height: Option<u32>,
+    pub assume_height_reached: bool,
+}
+
+impl After {
+    pub(crate) fn new(current_height: Option<u32>, assume_height_reached: bool) -> After {
+        After {
+            current_height,
+            assume_height_reached,
+        }
+    }
+}
+
+pub(crate) fn check_nsequence_rbf(rbf: Sequence, csv: Sequence) -> bool {
+    // The RBF value must enable relative timelocks
+    if !rbf.is_relative_lock_time() {
+        return false;
+    }
+
+    // Both values should be represented in the same unit (either time-based or
+    // block-height based)
+    if rbf.is_time_locked() != csv.is_time_locked() {
+        return false;
+    }
+
+    // The value should be at least `csv`
+    if rbf < csv {
+        return false;
+    }
+
+    true
+}
+
+impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for After {
+    fn check_after(&self, n: absolute::LockTime) -> bool {
+        if let Some(current_height) = self.current_height {
+            current_height >= n.to_consensus_u32()
+        } else {
+            self.assume_height_reached
+        }
+    }
+}
+
+pub struct Older {
+    pub current_height: Option<u32>,
+    pub create_height: Option<u32>,
+    pub assume_height_reached: bool,
+}
+
+impl Older {
+    pub(crate) fn new(
+        current_height: Option<u32>,
+        create_height: Option<u32>,
+        assume_height_reached: bool,
+    ) -> Older {
+        Older {
+            current_height,
+            create_height,
+            assume_height_reached,
+        }
+    }
+}
+
+impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for Older {
+    fn check_older(&self, n: Sequence) -> bool {
+        if let Some(current_height) = self.current_height {
+            // TODO: test >= / >
+            current_height
+                >= self
+                    .create_height
+                    .unwrap_or(0)
+                    .checked_add(n.to_consensus_u32())
+                    .expect("Overflowing addition")
+        } else {
+            self.assume_height_reached
+        }
+    }
+}
+
+pub(crate) type SecpCtx = Secp256k1<All>;
+
+#[cfg(test)]
+mod test {
+    // When nSequence is lower than this flag the timelock is interpreted as block-height-based,
+    // otherwise it's time-based
+    pub(crate) const SEQUENCE_LOCKTIME_TYPE_FLAG: u32 = 1 << 22;
+
+    use super::{check_nsequence_rbf, IsDust};
+    use crate::bitcoin::{Address, Network, Sequence};
+    use core::str::FromStr;
+
+    #[test]
+    fn test_is_dust() {
+        let script_p2pkh = Address::from_str("1GNgwA8JfG7Kc8akJ8opdNWJUihqUztfPe")
+            .unwrap()
+            .require_network(Network::Bitcoin)
+            .unwrap()
+            .script_pubkey();
+        assert!(script_p2pkh.is_p2pkh());
+        assert!(545.is_dust(&script_p2pkh));
+        assert!(!546.is_dust(&script_p2pkh));
+
+        let script_p2wpkh = Address::from_str("bc1qxlh2mnc0yqwas76gqq665qkggee5m98t8yskd8")
+            .unwrap()
+            .require_network(Network::Bitcoin)
+            .unwrap()
+            .script_pubkey();
+        assert!(script_p2wpkh.is_p2wpkh());
+        assert!(293.is_dust(&script_p2wpkh));
+        assert!(!294.is_dust(&script_p2wpkh));
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_msb_set() {
+        let result = check_nsequence_rbf(Sequence(0x80000000), Sequence(5000));
+        assert!(!result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_lt_csv() {
+        let result = check_nsequence_rbf(Sequence(4000), Sequence(5000));
+        assert!(!result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_different_unit() {
+        let result =
+            check_nsequence_rbf(Sequence(SEQUENCE_LOCKTIME_TYPE_FLAG + 5000), Sequence(5000));
+        assert!(!result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_mask() {
+        let result = check_nsequence_rbf(Sequence(0x3f + 10_000), Sequence(5000));
+        assert!(result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_same_unit_blocks() {
+        let result = check_nsequence_rbf(Sequence(10_000), Sequence(5000));
+        assert!(result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_same_unit_time() {
+        let result = check_nsequence_rbf(
+            Sequence(SEQUENCE_LOCKTIME_TYPE_FLAG + 10_000),
+            Sequence(SEQUENCE_LOCKTIME_TYPE_FLAG + 5000),
+        );
+        assert!(result);
+    }
+}
+
+
\ 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 index 867903996a..5b820b8755 100644 --- 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 @@ -93,6 +93,7 @@ 93 94 95 +96
const DB_MAGIC: &str = "bdk_wallet_electrum_example";
 const SEND_AMOUNT: Amount = Amount::from_sat(5000);
 const STOP_GAP: usize = 50;
@@ -101,19 +102,20 @@
 use std::io::Write;
 use std::str::FromStr;
 
-use bdk::bitcoin::{Address, Amount};
-use bdk::chain::collections::HashSet;
-use bdk::{bitcoin::Network, Wallet};
-use bdk::{KeychainKind, SignOptions};
 use bdk_electrum::{
     electrum_client::{self, ElectrumApi},
     ElectrumExt,
 };
 use bdk_file_store::Store;
+use bdk_wallet::bitcoin::{Address, Amount};
+use bdk_wallet::chain::collections::HashSet;
+use bdk_wallet::{bitcoin::Network, Wallet};
+use bdk_wallet::{KeychainKind, SignOptions};
 
 fn main() -> Result<(), anyhow::Error> {
     let db_path = std::env::temp_dir().join("bdk-electrum-example");
-    let db = Store::<bdk::wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), db_path)?;
+    let db =
+        Store::<bdk_wallet::wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), db_path)?;
     let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
     let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)";
 
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
index cf54c29f71..32bde96a8d 100644
--- 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
@@ -107,14 +107,15 @@
 107
 108
 109
+110
 
use std::{collections::BTreeSet, io::Write, str::FromStr};
 
-use bdk::{
+use bdk_esplora::{esplora_client, EsploraAsyncExt};
+use bdk_file_store::Store;
+use bdk_wallet::{
     bitcoin::{Address, Amount, Network, Script},
     KeychainKind, SignOptions, Wallet,
 };
-use bdk_esplora::{esplora_client, EsploraAsyncExt};
-use bdk_file_store::Store;
 
 const DB_MAGIC: &str = "bdk_wallet_esplora_async_example";
 const SEND_AMOUNT: Amount = Amount::from_sat(5000);
@@ -124,7 +125,8 @@
 #[tokio::main]
 async fn main() -> Result<(), anyhow::Error> {
     let db_path = std::env::temp_dir().join("bdk-esplora-async-example");
-    let db = Store::<bdk::wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), db_path)?;
+    let db =
+        Store::<bdk_wallet::wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), db_path)?;
     let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
     let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)";
 
diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_esplora_blocking/main.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_esplora_blocking/main.rs.html
index faf305fd9d..ff20b00209 100644
--- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_esplora_blocking/main.rs.html
+++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_esplora_blocking/main.rs.html
@@ -83,6 +83,7 @@
 83
 84
 85
+86
 
const DB_MAGIC: &str = "bdk_wallet_esplora_example";
 const SEND_AMOUNT: Amount = Amount::from_sat(1000);
 const STOP_GAP: usize = 5;
@@ -90,16 +91,17 @@
 
 use std::{collections::BTreeSet, io::Write, str::FromStr};
 
-use bdk::{
+use bdk_esplora::{esplora_client, EsploraExt};
+use bdk_file_store::Store;
+use bdk_wallet::{
     bitcoin::{Address, Amount, Network},
     KeychainKind, SignOptions, Wallet,
 };
-use bdk_esplora::{esplora_client, EsploraExt};
-use bdk_file_store::Store;
 
 fn main() -> Result<(), anyhow::Error> {
     let db_path = std::env::temp_dir().join("bdk-esplora-example");
-    let db = Store::<bdk::wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), db_path)?;
+    let db =
+        Store::<bdk_wallet::wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), db_path)?;
     let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
     let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)";
 
diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_rpc/main.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_rpc/main.rs.html
index b3f8ca2cd7..1bc47bdf01 100644
--- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_rpc/main.rs.html
+++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/wallet_rpc/main.rs.html
@@ -180,21 +180,24 @@
 180
 181
 182
-
use bdk::{
-    bitcoin::{Block, Network, Transaction},
-    wallet::Wallet,
-};
-use bdk_bitcoind_rpc::{
+183
+184
+185
+
use bdk_bitcoind_rpc::{
     bitcoincore_rpc::{Auth, Client, RpcApi},
     Emitter,
 };
 use bdk_file_store::Store;
+use bdk_wallet::{
+    bitcoin::{Block, Network, Transaction},
+    wallet::Wallet,
+};
 use clap::{self, Parser};
 use std::{path::PathBuf, sync::mpsc::sync_channel, thread::spawn, time::Instant};
 
 const DB_MAGIC: &str = "bdk-rpc-wallet-example";
 
-/// Bitcoind RPC example using `bdk::Wallet`.
+/// Bitcoind RPC example using `bdk_wallet::Wallet`.
 ///
 /// This syncs the chain block-by-block and prints the current balance, transaction count and UTXO
 /// count.
@@ -271,7 +274,10 @@
     let mut wallet = Wallet::new_or_load(
         &args.descriptor,
         args.change_descriptor.as_ref(),
-        Store::<bdk::wallet::ChangeSet>::open_or_create_new(DB_MAGIC.as_bytes(), args.db_path)?,
+        Store::<bdk_wallet::wallet::ChangeSet>::open_or_create_new(
+            DB_MAGIC.as_bytes(),
+            args.db_path,
+        )?,
         args.network,
     )?;
     println!(
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
index 0545165a77..d7035bcdc9 100644
--- 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
@@ -1 +1 @@
-main in wallet_electrum_example - Rust

Function wallet_electrum_example::main

source ·
pub(crate) fn main() -> Result<(), Error>
\ No newline at end of file +main in wallet_electrum_example - Rust

Function wallet_electrum_example::main

source ·
pub(crate) fn main() -> Result<(), 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 index 3c3db65571..197bb90194 100644 --- 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 @@ -1 +1 @@ -wallet_electrum_example - Rust

Constants

BATCH_SIZE ðŸ”’
DB_MAGIC ðŸ”’
SEND_AMOUNT ðŸ”’
STOP_GAP ðŸ”’

Functions

main ðŸ”’
\ No newline at end of file +wallet_electrum_example - Rust

Constants

BATCH_SIZE ðŸ”’
DB_MAGIC ðŸ”’
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/fn.main.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_async/fn.main.html index 59950c20fe..c19b13eb48 100644 --- 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 @@ -1 +1 @@ -main in wallet_esplora_async - Rust

Function wallet_esplora_async::main

source ·
pub(crate) fn main() -> Result<(), Error>
\ No newline at end of file +main in wallet_esplora_async - Rust

Function wallet_esplora_async::main

source ·
pub(crate) fn main() -> Result<(), 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 index 43bacaf475..e288042426 100644 --- 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 @@ -1 +1 @@ -wallet_esplora_async - Rust

Constants

DB_MAGIC ðŸ”’
SEND_AMOUNT ðŸ”’
STOP_GAP ðŸ”’

Functions

main ðŸ”’
\ No newline at end of file +wallet_esplora_async - Rust

Constants

DB_MAGIC ðŸ”’
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_blocking/fn.main.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_blocking/fn.main.html index 2ddb1db5ec..d10e425e3a 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_blocking/fn.main.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_blocking/fn.main.html @@ -1 +1 @@ -main in wallet_esplora_blocking - Rust

Function wallet_esplora_blocking::main

source ·
pub(crate) fn main() -> Result<(), Error>
\ No newline at end of file +main in wallet_esplora_blocking - Rust

Function wallet_esplora_blocking::main

source ·
pub(crate) fn main() -> Result<(), Error>
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_blocking/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_blocking/index.html index d85299e4f3..99745e1a0a 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_blocking/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_esplora_blocking/index.html @@ -1 +1 @@ -wallet_esplora_blocking - Rust

Constants

DB_MAGIC ðŸ”’
SEND_AMOUNT ðŸ”’
STOP_GAP ðŸ”’

Functions

main ðŸ”’
\ No newline at end of file +wallet_esplora_blocking - Rust

Constants

DB_MAGIC ðŸ”’
SEND_AMOUNT ðŸ”’
STOP_GAP ðŸ”’

Functions

main ðŸ”’
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/fn.main.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/fn.main.html index 1fd1908f8b..6abf69b4ff 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/fn.main.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/fn.main.html @@ -1 +1 @@ -main in wallet_rpc - Rust

Function wallet_rpc::main

source ·
pub(crate) fn main() -> Result<()>
\ No newline at end of file +main in wallet_rpc - Rust

Function wallet_rpc::main

source ·
pub(crate) fn main() -> Result<()>
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/index.html index 40d994a8b2..5a17eb49ec 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/index.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/index.html @@ -1 +1 @@ -wallet_rpc - Rust

Crate wallet_rpc

source ·

Structs

Bitcoind RPC example using bdk::Wallet.

Enums

Emission ðŸ”’

Constants

DB_MAGIC ðŸ”’

Functions

main ðŸ”’
\ No newline at end of file +wallet_rpc - Rust

Crate wallet_rpc

source ·

Structs

Bitcoind RPC example using bdk_wallet::Wallet.

Enums

Emission ðŸ”’

Constants

DB_MAGIC ðŸ”’

Functions

main ðŸ”’
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/sidebar-items.js index da3aef5734..48d556c0ce 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/sidebar-items.js +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"constant":[["DB_MAGIC",""]],"enum":[["Emission",""]],"fn":[["main",""]],"struct":[["Args","Bitcoind RPC example using `bdk::Wallet`."]]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"constant":[["DB_MAGIC",""]],"enum":[["Emission",""]],"fn":[["main",""]],"struct":[["Args","Bitcoind RPC example using `bdk_wallet::Wallet`."]]}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/struct.Args.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/struct.Args.html index 548bad437e..80b84edf2b 100644 --- a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/struct.Args.html +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wallet_rpc/struct.Args.html @@ -1,4 +1,4 @@ -Args in wallet_rpc - Rust

Struct wallet_rpc::Args

source ·
pub struct Args {
+Args in wallet_rpc - Rust

Struct wallet_rpc::Args

source ·
pub struct Args {
     pub descriptor: String,
     pub change_descriptor: Option<String>,
     pub start_height: u32,
@@ -8,7 +8,7 @@
     pub rpc_cookie: Option<PathBuf>,
     pub rpc_user: Option<String>,
     pub rpc_pass: Option<String>,
-}
Expand description

Bitcoind RPC example using bdk::Wallet.

+}
Expand description

Bitcoind RPC example using bdk_wallet::Wallet.

This syncs the chain block-by-block and prints the current balance, transaction count and UTXO count.

Fields§

§descriptor: String

Wallet descriptor